diff options
Diffstat (limited to 'drivers/gator/gator_events_mmapped.c')
-rw-r--r-- | drivers/gator/gator_events_mmapped.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/drivers/gator/gator_events_mmapped.c b/drivers/gator/gator_events_mmapped.c new file mode 100644 index 000000000000..f055e48d317a --- /dev/null +++ b/drivers/gator/gator_events_mmapped.c @@ -0,0 +1,209 @@ +/* + * Example events provider + * + * Copyright (C) ARM Limited 2010-2013. 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. + * + * Similar entries to those below must be present in the events.xml file. + * To add them to the events.xml, create an events-mmap.xml with the + * following contents and rebuild gatord: + * + * <counter_set name="mmapped_cnt" count="3"/> + * <category name="mmapped" counter_set="mmapped_cnt" per_cpu="no"> + * <event event="0x0" title="Simulated1" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/> + * <event event="0x1" title="Simulated2" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/> + * <event event="0x2" title="Simulated3" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/> + * </category> + * + * When adding custom events, be sure do the following + * - add any needed .c files to the gator driver Makefile + * - call gator_events_install in the events init function + * - add the init function to GATOR_EVENTS_LIST in gator_main.c + * - add a new events-*.xml file to the gator daemon and rebuild + */ + +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ratelimit.h> + +#include "gator.h" + +#define MMAPPED_COUNTERS_NUM 3 + +static int mmapped_global_enabled; + +static struct { + unsigned long enabled; + unsigned long event; + unsigned long key; +} mmapped_counters[MMAPPED_COUNTERS_NUM]; + +static int mmapped_buffer[MMAPPED_COUNTERS_NUM * 2]; + +static s64 prev_time; + +/* Adds mmapped_cntX directories and enabled, event, and key files to /dev/gator/events */ +static int gator_events_mmapped_create_files(struct super_block *sb, + struct dentry *root) +{ + int i; + + for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) { + char buf[16]; + struct dentry *dir; + + snprintf(buf, sizeof(buf), "mmapped_cnt%d", i); + dir = gatorfs_mkdir(sb, root, buf); + if (WARN_ON(!dir)) + return -1; + gatorfs_create_ulong(sb, dir, "enabled", + &mmapped_counters[i].enabled); + gatorfs_create_ulong(sb, dir, "event", + &mmapped_counters[i].event); + gatorfs_create_ro_ulong(sb, dir, "key", + &mmapped_counters[i].key); + } + + return 0; +} + +static int gator_events_mmapped_start(void) +{ + int i; + struct timespec ts; + + getnstimeofday(&ts); + prev_time = timespec_to_ns(&ts); + + mmapped_global_enabled = 0; + for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) { + if (mmapped_counters[i].enabled) { + mmapped_global_enabled = 1; + break; + } + } + + return 0; +} + +static void gator_events_mmapped_stop(void) +{ +} + +/* This function "simulates" counters, generating values of fancy + * functions like sine or triangle... */ +static int mmapped_simulate(int counter, int delta_in_us) +{ + int result = 0; + + switch (counter) { + case 0: /* sort-of-sine */ + { + static int t = 0; + int x; + + t += delta_in_us; + if (t > 2048000) + t = 0; + + if (t % 1024000 < 512000) + x = 512000 - (t % 512000); + else + x = t % 512000; + + result = 32 * x / 512000; + result = result * result; + + if (t < 1024000) + result = 1922 - result; + } + break; + case 1: /* triangle */ + { + static int v, d = 1; + + v = v + d * delta_in_us; + if (v < 0) { + v = 0; + d = 1; + } else if (v > 1000000) { + v = 1000000; + d = -1; + } + + result = v; + } + break; + case 2: /* PWM signal */ + { + static int dc, x, t = 0; + + t += delta_in_us; + if (t > 1000000) + t = 0; + if (x / 1000000 != (x + delta_in_us) / 1000000) + dc = (dc + 100000) % 1000000; + x += delta_in_us; + + result = t < dc ? 0 : 10; + } + break; + } + + return result; +} + +static int gator_events_mmapped_read(int **buffer) +{ + int i; + int len = 0; + int delta_in_us; + struct timespec ts; + s64 time; + + /* System wide counters - read from one core only */ + if (!on_primary_core() || !mmapped_global_enabled) + return 0; + + getnstimeofday(&ts); + time = timespec_to_ns(&ts); + delta_in_us = (int)(time - prev_time) / 1000; + prev_time = time; + + for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) { + if (mmapped_counters[i].enabled) { + mmapped_buffer[len++] = mmapped_counters[i].key; + mmapped_buffer[len++] = + mmapped_simulate(mmapped_counters[i].event, + delta_in_us); + } + } + + if (buffer) + *buffer = mmapped_buffer; + + return len; +} + +static struct gator_interface gator_events_mmapped_interface = { + .create_files = gator_events_mmapped_create_files, + .start = gator_events_mmapped_start, + .stop = gator_events_mmapped_stop, + .read = gator_events_mmapped_read, +}; + +/* Must not be static! */ +int __init gator_events_mmapped_init(void) +{ + int i; + + for (i = 0; i < MMAPPED_COUNTERS_NUM; i++) { + mmapped_counters[i].enabled = 0; + mmapped_counters[i].key = gator_events_get_key(); + } + + return gator_events_install(&gator_events_mmapped_interface); +} |