]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blob - driver/gator_events_l2c-310.c
gator-daemon: Fix sequence-point compile error
[android-sdk/arm-ds5-gator.git] / driver / gator_events_l2c-310.c
1 /**
2  * l2c310 (L2 Cache Controller) event counters for gator
3  *
4  * Copyright (C) ARM Limited 2010-2012. All rights reserved.
5  *
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.
9  */
11 #include <linux/init.h>
12 #include <linux/io.h>
13 #include <asm/hardware/cache-l2x0.h>
15 #include "gator.h"
17 #define L2C310_COUNTERS_NUM 2
19 static struct {
20         unsigned long enabled;
21         unsigned long event;
22         unsigned long key;
23 } l2c310_counters[L2C310_COUNTERS_NUM];
25 static int l2c310_buffer[L2C310_COUNTERS_NUM * 2];
27 static void __iomem *l2c310_base;
31 static void gator_events_l2c310_reset_counters(void)
32 {
33         u32 val = readl(l2c310_base + L2X0_EVENT_CNT_CTRL);
35         val |= ((1 << L2C310_COUNTERS_NUM) - 1) << 1;
37         writel(val, l2c310_base + L2X0_EVENT_CNT_CTRL);
38 }
41 static int gator_events_l2c310_create_files(struct super_block *sb,
42                 struct dentry *root)
43 {
44         int i;
46         for (i = 0; i < L2C310_COUNTERS_NUM; i++) {
47                 char buf[16];
48                 struct dentry *dir;
50                 snprintf(buf, sizeof(buf), "L2C-310_cnt%d", i);
51                 dir = gatorfs_mkdir(sb, root, buf);
52                 if (WARN_ON(!dir))
53                         return -1;
54                 gatorfs_create_ulong(sb, dir, "enabled",
55                                 &l2c310_counters[i].enabled);
56                 gatorfs_create_ulong(sb, dir, "event",
57                                 &l2c310_counters[i].event);
58                 gatorfs_create_ro_ulong(sb, dir, "key",
59                                 &l2c310_counters[i].key);
60         }
62         return 0;
63 }
65 static int gator_events_l2c310_start(void)
66 {
67         static const unsigned long l2x0_event_cntx_cfg[L2C310_COUNTERS_NUM] = {
68                 L2X0_EVENT_CNT0_CFG,
69                 L2X0_EVENT_CNT1_CFG,
70         };
71         int i;
73         /* Counter event sources */
74         for (i = 0; i < L2C310_COUNTERS_NUM; i++)
75                 writel((l2c310_counters[i].event & 0xf) << 2,
76                                 l2c310_base + l2x0_event_cntx_cfg[i]);
78         gator_events_l2c310_reset_counters();
80         /* Event counter enable */
81         writel(1, l2c310_base + L2X0_EVENT_CNT_CTRL);
83         return 0;
84 }
86 static void gator_events_l2c310_stop(void)
87 {
88         /* Event counter disable */
89         writel(0, l2c310_base + L2X0_EVENT_CNT_CTRL);
90 }
92 static int gator_events_l2c310_read(int **buffer)
93 {
94         static const unsigned long l2x0_event_cntx_val[L2C310_COUNTERS_NUM] = {
95                 L2X0_EVENT_CNT0_VAL,
96                 L2X0_EVENT_CNT1_VAL,
97         };
98         int i;
99         int len = 0;
101         if (smp_processor_id())
102                 return 0;
104         for (i = 0; i < L2C310_COUNTERS_NUM; i++) {
105                 if (l2c310_counters[i].enabled) {
106                         l2c310_buffer[len++] = l2c310_counters[i].key;
107                         l2c310_buffer[len++] = readl(l2c310_base +
108                                         l2x0_event_cntx_val[i]);
109                 }
110         }
111         
112         /* l2c310 counters are saturating, not wrapping in case of overflow */
113         gator_events_l2c310_reset_counters();
115         if (buffer)
116                 *buffer = l2c310_buffer;
118         return len;
121 static struct gator_interface gator_events_l2c310_interface = {
122         .create_files = gator_events_l2c310_create_files,
123         .start = gator_events_l2c310_start,
124         .stop = gator_events_l2c310_stop,
125         .read = gator_events_l2c310_read,
126 };
128 static void __maybe_unused gator_events_l2c310_probe(unsigned long phys)
130         if (l2c310_base)
131                 return;
133         l2c310_base = ioremap(phys, SZ_4K);
134         if (l2c310_base) {
135                 u32 cache_id = readl(l2c310_base + L2X0_CACHE_ID);
137                 if ((cache_id & 0xff0003c0) != 0x410000c0) {
138                         iounmap(l2c310_base);
139                         l2c310_base = NULL;
140                 }
141         }
144 int gator_events_l2c310_init(void)
146         int i;
148         if (gator_cpuid() != CORTEX_A5 && gator_cpuid() != CORTEX_A9)
149                 return -1;
151 #if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_S5PV310)
152         gator_events_l2c310_probe(0x10502000);
153 #endif
154 #if defined(CONFIG_ARCH_OMAP4)
155         gator_events_l2c310_probe(0x48242000);
156 #endif
157 #if defined(CONFIG_ARCH_TEGRA)
158         gator_events_l2c310_probe(0x50043000);
159 #endif
160 #if defined(CONFIG_ARCH_U8500)
161         gator_events_l2c310_probe(0xa0412000);
162 #endif
163 #if defined(CONFIG_ARCH_VEXPRESS)
164         // A9x4 core tile (HBI-0191)
165         gator_events_l2c310_probe(0x1e00a000);
166         // New memory map tiles
167         gator_events_l2c310_probe(0x2c0f0000);
168 #endif
169         if (!l2c310_base)
170                 return -1;
172         for (i = 0; i < L2C310_COUNTERS_NUM; i++) {
173                 l2c310_counters[i].enabled = 0;
174                 l2c310_counters[i].key = gator_events_get_key();
175         }
177         return gator_events_install(&gator_events_l2c310_interface);
179 gator_events_init(gator_events_l2c310_init);