]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blob - driver/gator_events_power.c
gator-driver: ARM DS-5.9 Streamline gator driver (RC2)
[android-sdk/arm-ds5-gator.git] / driver / gator_events_power.c
1 /**
2  * Copyright (C) ARM Limited 2011-2012. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
10 #include "gator.h"
11 #include <linux/slab.h>
12 #include <linux/cpufreq.h>
13 #include <trace/events/power.h>
15 // cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38
16 // the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86
17 // CPU Idle is currently disabled in the .xml
18 #if GATOR_CPU_FREQ_SUPPORT
19 enum {
20         POWER_CPU_FREQ,
21         POWER_CPU_IDLE,
22         POWER_TOTAL
23 };
25 static ulong power_cpu_enabled[POWER_TOTAL];
26 static ulong power_cpu_key[POWER_TOTAL];
27 static DEFINE_PER_CPU(ulong[POWER_TOTAL], power);
28 static DEFINE_PER_CPU(ulong[POWER_TOTAL], prev);
29 static DEFINE_PER_CPU(int *, powerGet);
31 GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int cpu))
32 {
33         per_cpu(power, cpu)[POWER_CPU_FREQ] = frequency * 1000;
34 }
36 GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
37 {
38         per_cpu(power, cpu)[POWER_CPU_IDLE] = state;
39 }
41 static int gator_events_power_create_files(struct super_block *sb, struct dentry *root)
42 {
43         struct dentry *dir;
45         // cpu_frequency
46         dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_freq");
47         if (!dir) {
48                 return -1;
49         }
50         gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_FREQ]);
51         gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_FREQ]);
53         // cpu_idle
54         dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_idle");
55         if (!dir) {
56                 return -1;
57         }
58         gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_IDLE]);
59         gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_IDLE]);
61         return 0;
62 }
64 static int gator_events_power_populate(int cpu, int** buffer)
65 {
66         int i, len = 0;
68         for (i = 0; i < POWER_TOTAL; i++) {
69                 if (power_cpu_enabled[i]) {
70                         if (per_cpu(power, cpu)[i] != per_cpu(prev, cpu)[i]) {
71                                 per_cpu(prev, cpu)[i] = per_cpu(power, cpu)[i];
72                                 per_cpu(powerGet, cpu)[len++] = power_cpu_key[i];
73                                 per_cpu(powerGet, cpu)[len++] = per_cpu(power, cpu)[i];
74                         }
75                 }
76         }
78         if (buffer)
79                 *buffer = per_cpu(powerGet, cpu);
81         return len;
82 }
84 static int gator_events_power_online(int** buffer)
85 {
86         int i, cpu = smp_processor_id();
87         for (i = 0; i < POWER_TOTAL; i++)
88                 per_cpu(prev, cpu)[i] = -1;
89         per_cpu(power, cpu)[POWER_CPU_FREQ] = cpufreq_quick_get(cpu) * 1000;
90         return gator_events_power_populate(cpu, buffer);
91 }
93 static int gator_events_power_offline(int** buffer)
94 {
95         int cpu = smp_processor_id();
96         // Set frequency to zero on an offline
97         per_cpu(power, cpu)[POWER_CPU_FREQ] = 0;
98         return gator_events_power_populate(cpu, buffer);
99 }
101 static int gator_events_power_start(void)
103         int cpu;
105         for_each_present_cpu(cpu) {
106                 per_cpu(powerGet, cpu) = kmalloc(POWER_TOTAL * 2, GFP_KERNEL);
107                 if (!per_cpu(powerGet, cpu))
108                         return -1;
109         }
111         // register tracepoints
112         if (power_cpu_enabled[POWER_CPU_FREQ])
113                 if (GATOR_REGISTER_TRACE(cpu_frequency))
114                         goto fail_cpu_frequency_exit;
115         if (power_cpu_enabled[POWER_CPU_IDLE])
116                 if (GATOR_REGISTER_TRACE(cpu_idle))
117                         goto fail_cpu_idle_exit;
118         pr_debug("gator: registered power event tracepoints\n");
120         return 0;
122         // unregister tracepoints on error
123 fail_cpu_idle_exit:
124         GATOR_UNREGISTER_TRACE(cpu_frequency);
125 fail_cpu_frequency_exit:
126         pr_err("gator: power event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
128         return -1;
131 static void gator_events_power_stop(void)
133         int i, cpu;
134         if (power_cpu_enabled[POWER_CPU_FREQ])
135                 GATOR_UNREGISTER_TRACE(cpu_frequency);
136         if (power_cpu_enabled[POWER_CPU_IDLE])
137                 GATOR_UNREGISTER_TRACE(cpu_idle);
138         pr_debug("gator: unregistered power event tracepoints\n");
140         for (i = 0; i < POWER_TOTAL; i++) {
141                 power_cpu_enabled[i] = 0;
142         }
144         for_each_present_cpu(cpu) {
145                 kfree(per_cpu(powerGet, cpu));
146         }
149 static int gator_events_power_read(int **buffer)
151         return gator_events_power_populate(smp_processor_id(), buffer);
154 static struct gator_interface gator_events_power_interface = {
155         .create_files = gator_events_power_create_files,
156         .online = gator_events_power_online,
157         .offline = gator_events_power_offline,
158         .start = gator_events_power_start,
159         .stop = gator_events_power_stop,
160         .read = gator_events_power_read,
161 };
162 #endif
164 int gator_events_power_init(void)
166 #if (GATOR_CPU_FREQ_SUPPORT)
167         int i;
168         for (i = 0; i < POWER_TOTAL; i++) {
169                 power_cpu_enabled[i] = 0;
170                 power_cpu_key[i] = gator_events_get_key();
171         }
173         return gator_events_install(&gator_events_power_interface);
174 #else
175         return -1;
176 #endif
178 gator_events_init(gator_events_power_init);