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 }
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;
119 }
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)
129 {
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 }
142 }
144 int gator_events_l2c310_init(void)
145 {
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);
178 }
179 gator_events_init(gator_events_l2c310_init);