2 * Example events provider
4 * Copyright (C) ARM Limited 2010-2013. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Similar entries to those below must be present in the events.xml file.
11 * To add them to the events.xml, create an events-mmap.xml with the
12 * following contents and rebuild gatord:
14 * <counter_set name="mmaped_cnt" count="3"/>
15 * <category name="mmaped" counter_set="mmaped_cnt" per_cpu="no">
16 * <event event="0x0" title="Simulated1" name="Sine" display="maximum" average_selection="yes" description="Sort-of-sine"/>
17 * <event event="0x1" title="Simulated2" name="Triangle" display="maximum" average_selection="yes" description="Triangular wave"/>
18 * <event event="0x2" title="Simulated3" name="PWM" display="maximum" average_selection="yes" description="PWM Signal"/>
22 #include <linux/init.h>
24 #include <linux/ratelimit.h>
28 #define MMAPED_COUNTERS_NUM 3
31 unsigned long enabled;
34 } mmaped_counters[MMAPED_COUNTERS_NUM];
36 static int mmaped_buffer[MMAPED_COUNTERS_NUM * 2];
39 static void __iomem *mmaped_base;
46 /* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */
47 static int gator_events_mmaped_create_files(struct super_block *sb,
52 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
56 snprintf(buf, sizeof(buf), "mmaped_cnt%d", i);
57 dir = gatorfs_mkdir(sb, root, buf);
60 gatorfs_create_ulong(sb, dir, "enabled",
61 &mmaped_counters[i].enabled);
62 gatorfs_create_ulong(sb, dir, "event",
63 &mmaped_counters[i].event);
64 gatorfs_create_ro_ulong(sb, dir, "key",
65 &mmaped_counters[i].key);
71 static int gator_events_mmaped_start(void)
74 for (i = 0; i < MMAPED_COUNTERS_NUM; i++)
75 writel(mmaped_counters[i].event,
76 mmaped_base + COUNTERS_CONFIG_OFFSET[i]);
78 writel(ENABLED, COUNTERS_CONTROL_OFFSET);
84 prev_time = timespec_to_ns(&ts);
90 static void gator_events_mmaped_stop(void)
93 writel(DISABLED, COUNTERS_CONTROL_OFFSET);
98 /* This function "simulates" counters, generating values of fancy
99 * functions like sine or triangle... */
100 static int mmaped_simulate(int counter, int delta_in_us)
105 case 0: /* sort-of-sine */
114 if (t % 1024000 < 512000)
115 x = 512000 - (t % 512000);
119 result = 32 * x / 512000;
120 result = result * result;
123 result = 1922 - result;
126 case 1: /* triangle */
130 v = v + d * delta_in_us;
134 } else if (v > 1000000) {
142 case 2: /* PWM signal */
144 static int dc, x, t = 0;
149 if (x / 1000000 != (x + delta_in_us) / 1000000)
150 dc = (dc + 100000) % 1000000;
153 result = t < dc ? 0 : 10;
162 static int gator_events_mmaped_read(int **buffer)
172 /* System wide counters - read from one core only */
173 if (!on_primary_core())
178 time = timespec_to_ns(&ts);
179 delta_in_us = (int)(time - prev_time) / 1000;
183 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
184 if (mmaped_counters[i].enabled) {
185 mmaped_buffer[len++] = mmaped_counters[i].key;
187 mmaped_buffer[len++] =
188 readl(mmaped_base + COUNTERS_VALUE_OFFSET[i]);
190 mmaped_buffer[len++] =
191 mmaped_simulate(mmaped_counters[i].event,
198 *buffer = mmaped_buffer;
203 static struct gator_interface gator_events_mmaped_interface = {
204 .create_files = gator_events_mmaped_create_files,
205 .start = gator_events_mmaped_start,
206 .stop = gator_events_mmaped_stop,
207 .read = gator_events_mmaped_read,
210 /* Must not be static! */
211 int __init gator_events_mmaped_init(void)
216 mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K);
221 for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
222 mmaped_counters[i].enabled = 0;
223 mmaped_counters[i].key = gator_events_get_key();
226 return gator_events_install(&gator_events_mmaped_interface);
229 gator_events_init(gator_events_mmaped_init);