aboutsummaryrefslogtreecommitdiff
path: root/driver/gator_events_ccn-504.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/gator_events_ccn-504.c')
-rw-r--r--driver/gator_events_ccn-504.c346
1 files changed, 0 insertions, 346 deletions
diff --git a/driver/gator_events_ccn-504.c b/driver/gator_events_ccn-504.c
deleted file mode 100644
index 62d994c..0000000
--- a/driver/gator_events_ccn-504.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/module.h>
-
-#include "gator.h"
-
-#define NUM_REGIONS 256
-#define REGION_SIZE (64*1024)
-#define REGION_DEBUG 1
-#define REGION_XP 64
-#define NUM_XPS 11
-
-// DT (Debug) region
-#define PMEVCNTSR0 0x0150
-#define PMCCNTRSR 0x0190
-#define PMCR 0x01A8
-#define PMSR 0x01B0
-#define PMSR_REQ 0x01B8
-#define PMSR_CLR 0x01C0
-
-// XP region
-#define DT_CONFIG 0x0300
-#define DT_CONTROL 0x0370
-
-// Multiple
-#define PMU_EVENT_SEL 0x0600
-#define OLY_ID 0xFF00
-
-#define CCNT 4
-#define CNTMAX (CCNT + 1)
-
-#define get_pmu_event_id(event) (((event) >> 0) & 0xFF)
-#define get_node_type(event) (((event) >> 8) & 0xFF)
-#define get_region(event) (((event) >> 16) & 0xFF)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
-
-// From kernel/params.c
-#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
- int param_set_##name(const char *val, struct kernel_param *kp) \
- { \
- tmptype l; \
- int ret; \
- \
- if (!val) return -EINVAL; \
- ret = strtolfn(val, 0, &l); \
- if (ret == -EINVAL || ((type)l != l)) \
- return -EINVAL; \
- *((type *)kp->arg) = l; \
- return 0; \
- } \
- int param_get_##name(char *buffer, struct kernel_param *kp) \
- { \
- return sprintf(buffer, format, *((type *)kp->arg)); \
- }
-
-#else
-
-// From kernel/params.c
-#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \
- int param_set_##name(const char *val, const struct kernel_param *kp) \
- { \
- tmptype l; \
- int ret; \
- \
- ret = strtolfn(val, 0, &l); \
- if (ret < 0 || ((type)l != l)) \
- return ret < 0 ? ret : -EINVAL; \
- *((type *)kp->arg) = l; \
- return 0; \
- } \
- int param_get_##name(char *buffer, const struct kernel_param *kp) \
- { \
- return scnprintf(buffer, PAGE_SIZE, format, \
- *((type *)kp->arg)); \
- } \
- struct kernel_param_ops param_ops_##name = { \
- .set = param_set_##name, \
- .get = param_get_##name, \
- }; \
- EXPORT_SYMBOL(param_set_##name); \
- EXPORT_SYMBOL(param_get_##name); \
- EXPORT_SYMBOL(param_ops_##name)
-
-#endif
-
-STANDARD_PARAM_DEF(u64, u64, "%llu", u64, kstrtoull);
-
-// From include/linux/moduleparam.h
-#define param_check_u64(name, p) __param_check(name, p, u64)
-
-MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address");
-static u64 ccn504_addr = 0;
-module_param(ccn504_addr, u64, 0444);
-
-static void __iomem *gator_events_ccn504_base;
-static bool gator_events_ccn504_global_enabled;
-static unsigned long gator_events_ccn504_enabled[CNTMAX];
-static unsigned long gator_events_ccn504_event[CNTMAX];
-static unsigned long gator_events_ccn504_key[CNTMAX];
-static int gator_events_ccn504_buffer[2*CNTMAX];
-static int gator_events_ccn504_prev[CNTMAX];
-
-static void gator_events_ccn504_create_shutdown(void)
-{
- if (gator_events_ccn504_base != NULL) {
- iounmap(gator_events_ccn504_base);
- }
-}
-
-static int gator_events_ccn504_create_files(struct super_block *sb, struct dentry *root)
-{
- struct dentry *dir;
- int i;
- char buf[32];
-
- for (i = 0; i < CNTMAX; ++i) {
- if (i == CCNT) {
- snprintf(buf, sizeof(buf), "CCN-504_ccnt");
- } else {
- snprintf(buf, sizeof(buf), "CCN-504_cnt%i", i);
- }
- dir = gatorfs_mkdir(sb, root, buf);
- if (!dir) {
- return -1;
- }
-
- gatorfs_create_ulong(sb, dir, "enabled", &gator_events_ccn504_enabled[i]);
- if (i != CCNT) {
- gatorfs_create_ulong(sb, dir, "event", &gator_events_ccn504_event[i]);
- }
- gatorfs_create_ro_ulong(sb, dir, "key", &gator_events_ccn504_key[i]);
- }
-
- return 0;
-}
-
-static void gator_events_ccn504_set_dt_config(int xp_node_id, int event_num, int value)
-{
- u32 dt_config;
-
- dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
- dt_config |= (value + event_num) << (4*event_num);
- writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG);
-}
-
-static int gator_events_ccn504_start(void)
-{
- int i;
-
- gator_events_ccn504_global_enabled = 0;
- for (i = 0; i < CNTMAX; ++i) {
- if (gator_events_ccn504_enabled[i]) {
- gator_events_ccn504_global_enabled = 1;
- break;
- }
- }
-
- if (!gator_events_ccn504_global_enabled) {
- return 0;
- }
-
- memset(&gator_events_ccn504_prev, 0x80, sizeof(gator_events_ccn504_prev));
-
- // Disable INTREQ on overflow
- // [6] ovfl_intr_en = 0
- // perhaps set to 1?
- // [5] cntr_rst = 0
- // No register paring
- // [4:1] cntcfg = 0
- // Enable PMU features
- // [0] pmu_en = 1
- writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR);
-
- // Configure the XPs
- for (i = 0; i < NUM_XPS; ++i) {
- int dt_control;
-
- // Pass on all events
- writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
-
- // Enable PMU capability
- // [0] dt_enable = 1
- dt_control = readl(gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
- dt_control |= 0x1;
- writel(dt_control, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL);
- }
-
- // Assume no other pmu_event_sel registers are set
-
- // cycle counter does not need to be enabled
- for (i = 0; i < CCNT; ++i) {
- int pmu_event_id;
- int node_type;
- int region;
- u32 pmu_event_sel;
- u32 oly_id_whole;
- u32 oly_id;
- u32 node_id;
-
- if (!gator_events_ccn504_enabled[i]) {
- continue;
- }
-
- pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]);
- node_type = get_node_type(gator_events_ccn504_event[i]);
- region = get_region(gator_events_ccn504_event[i]);
-
- // Verify the node_type
- oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID);
- oly_id = oly_id_whole & 0x1F;
- node_id = (oly_id_whole >> 8) & 0x7F;
- if ((oly_id != node_type) ||
- ((node_type == 0x16) && ((oly_id != 0x14) && (oly_id != 0x15) && (oly_id != 0x16) && (oly_id != 0x18) && (oly_id != 0x19) && (oly_id != 0x1A)))) {
- printk(KERN_ERR "gator: oly_id is 0x%x expected 0x%x\n", oly_id, node_type);
- return -1;
- }
-
- // Set the control register
- pmu_event_sel = readl(gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
- switch (node_type) {
- case 0x08: // XP
- pmu_event_sel |= pmu_event_id << (7*i);
- gator_events_ccn504_set_dt_config(node_id, i, 0x4);
- break;
- case 0x04: // HN-F
- case 0x16: // RN-I
- case 0x10: // SBAS
- pmu_event_sel |= pmu_event_id << (4*i);
- gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC);
- break;
- }
- writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
- }
-
- return 0;
-}
-
-static void gator_events_ccn504_stop(void)
-{
- int i;
-
- if (!gator_events_ccn504_global_enabled) {
- return;
- }
-
- // cycle counter does not need to be disabled
- for (i = 0; i < CCNT; ++i) {
- int region;
-
- if (!gator_events_ccn504_enabled[i]) {
- continue;
- }
-
- region = get_region(gator_events_ccn504_event[i]);
-
- writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL);
- }
-
- // Clear dt_config
- for (i = 0; i < NUM_XPS; ++i) {
- writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG);
- }
-}
-
-static int gator_events_ccn504_read(int **buffer)
-{
- int i;
- int len = 0;
- int value;
-
- if (!on_primary_core() || !gator_events_ccn504_global_enabled) {
- return 0;
- }
-
- // Verify the pmsr register is zero
- while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0);
-
- // Request a PMU snapshot
- writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ);
-
- // Wait for the snapshot
- while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0);
-
- // Read the shadow registers
- for (i = 0; i < CNTMAX; ++i) {
- if (!gator_events_ccn504_enabled[i]) {
- continue;
- }
-
- value = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i));
- if (gator_events_ccn504_prev[i] != 0x80808080) {
- gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i];
- gator_events_ccn504_buffer[len++] = value - gator_events_ccn504_prev[i];
- }
- gator_events_ccn504_prev[i] = value;
-
- // Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does?
- }
-
- // Clear the PMU snapshot status
- writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR);
-
- if (buffer)
- *buffer = gator_events_ccn504_buffer;
-
- return len;
-}
-
-static struct gator_interface gator_events_ccn504_interface = {
- .shutdown = gator_events_ccn504_create_shutdown,
- .create_files = gator_events_ccn504_create_files,
- .start = gator_events_ccn504_start,
- .stop = gator_events_ccn504_stop,
- .read = gator_events_ccn504_read,
-};
-
-int gator_events_ccn504_init(void)
-{
- int i;
-
- if (ccn504_addr == 0) {
- return -1;
- }
-
- gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE);
- if (gator_events_ccn504_base == NULL) {
- printk(KERN_ERR "gator: ioremap returned NULL\n");
- return -1;
- }
-
- for (i = 0; i < CNTMAX; ++i) {
- gator_events_ccn504_enabled[i] = 0;
- gator_events_ccn504_event[i] = 0;
- gator_events_ccn504_key[i] = gator_events_get_key();
- }
-
- return gator_events_install(&gator_events_ccn504_interface);
-}