ARM: tizen_odroid_defconfig: Change the default cpufreq governor
[platform/kernel/linux-exynos.git] / drivers / gator / gator_events_l2c-310.c
1 /**
2  * l2c310 (L2 Cache Controller) event counters for gator
3  *
4  * Copyright (C) ARM Limited 2010-2016. 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  */
10
11 #include <linux/init.h>
12 #include <linux/io.h>
13 #include <linux/module.h>
14 #if defined(CONFIG_OF)
15 #include <linux/of.h>
16 #include <linux/of_address.h>
17 #endif
18 #include <asm/hardware/cache-l2x0.h>
19
20 #include "gator.h"
21
22 #define L2C310_COUNTERS_NUM 2
23
24 static struct {
25         unsigned long enabled;
26         unsigned long event;
27         unsigned long key;
28 } l2c310_counters[L2C310_COUNTERS_NUM];
29
30 static int l2c310_buffer[L2C310_COUNTERS_NUM * 2];
31
32 static void __iomem *l2c310_base;
33
34 static void gator_events_l2c310_reset_counters(void)
35 {
36         u32 val = readl(l2c310_base + L2X0_EVENT_CNT_CTRL);
37
38         val |= ((1 << L2C310_COUNTERS_NUM) - 1) << 1;
39
40         writel(val, l2c310_base + L2X0_EVENT_CNT_CTRL);
41 }
42
43 static int gator_events_l2c310_create_files(struct super_block *sb,
44                                             struct dentry *root)
45 {
46         int i;
47
48         for (i = 0; i < L2C310_COUNTERS_NUM; i++) {
49                 char buf[16];
50                 struct dentry *dir;
51
52                 snprintf(buf, sizeof(buf), "L2C-310_cnt%d", i);
53                 dir = gatorfs_mkdir(sb, root, buf);
54                 if (WARN_ON(!dir))
55                         return -1;
56                 gatorfs_create_ulong(sb, dir, "enabled",
57                                      &l2c310_counters[i].enabled);
58                 gatorfs_create_ulong(sb, dir, "event",
59                                      &l2c310_counters[i].event);
60                 gatorfs_create_ro_ulong(sb, dir, "key",
61                                         &l2c310_counters[i].key);
62         }
63
64         return 0;
65 }
66
67 static int gator_events_l2c310_start(void)
68 {
69         static const unsigned long l2x0_event_cntx_cfg[L2C310_COUNTERS_NUM] = {
70                 L2X0_EVENT_CNT0_CFG,
71                 L2X0_EVENT_CNT1_CFG,
72         };
73         int i;
74
75         /* Counter event sources */
76         for (i = 0; i < L2C310_COUNTERS_NUM; i++)
77                 writel((l2c310_counters[i].event & 0xf) << 2,
78                        l2c310_base + l2x0_event_cntx_cfg[i]);
79
80         gator_events_l2c310_reset_counters();
81
82         /* Event counter enable */
83         writel(1, l2c310_base + L2X0_EVENT_CNT_CTRL);
84
85         return 0;
86 }
87
88 static void gator_events_l2c310_stop(void)
89 {
90         /* Event counter disable */
91         writel(0, l2c310_base + L2X0_EVENT_CNT_CTRL);
92 }
93
94 static int gator_events_l2c310_read(int **buffer, bool sched_switch)
95 {
96         static const unsigned long l2x0_event_cntx_val[L2C310_COUNTERS_NUM] = {
97                 L2X0_EVENT_CNT0_VAL,
98                 L2X0_EVENT_CNT1_VAL,
99         };
100         int i;
101         int len = 0;
102
103         if (!on_primary_core())
104                 return 0;
105
106         for (i = 0; i < L2C310_COUNTERS_NUM; i++) {
107                 if (l2c310_counters[i].enabled) {
108                         l2c310_buffer[len++] = l2c310_counters[i].key;
109                         l2c310_buffer[len++] = readl(l2c310_base +
110                                                      l2x0_event_cntx_val[i]);
111                 }
112         }
113
114         /* l2c310 counters are saturating, not wrapping in case of overflow */
115         gator_events_l2c310_reset_counters();
116
117         if (buffer)
118                 *buffer = l2c310_buffer;
119
120         return len;
121 }
122
123 static struct gator_interface gator_events_l2c310_interface = {
124         .name = "l2c-310",
125         .create_files = gator_events_l2c310_create_files,
126         .start = gator_events_l2c310_start,
127         .stop = gator_events_l2c310_stop,
128         .read = gator_events_l2c310_read,
129 };
130
131 #define L2C310_ADDR_PROBE (~0)
132
133 MODULE_PARM_DESC(l2c310_addr, "L2C310 physical base address (0 to disable)");
134 static unsigned long l2c310_addr = L2C310_ADDR_PROBE;
135 module_param(l2c310_addr, ulong, 0444);
136
137 static void __iomem *gator_events_l2c310_probe(void)
138 {
139         phys_addr_t variants[] = {
140 #if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_S5PV310)
141                 0x10502000,
142 #endif
143 #if defined(CONFIG_ARCH_OMAP4)
144                 0x48242000,
145 #endif
146 #if defined(CONFIG_ARCH_TEGRA)
147                 0x50043000,
148 #endif
149 #if defined(CONFIG_ARCH_U8500)
150                 0xa0412000,
151 #endif
152 #if defined(CONFIG_ARCH_VEXPRESS)
153                 0x1e00a000, /* A9x4 core tile (HBI-0191) */
154                 0x2c0f0000, /* New memory map tiles */
155 #endif
156         };
157         int i;
158         void __iomem *base;
159 #if defined(CONFIG_OF)
160         struct device_node *node = of_find_all_nodes(NULL);
161
162         if (node) {
163                 of_node_put(node);
164
165                 node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
166                 base = of_iomap(node, 0);
167                 of_node_put(node);
168
169                 return base;
170         }
171 #endif
172
173         for (i = 0; i < ARRAY_SIZE(variants); i++) {
174                 base = ioremap(variants[i], SZ_4K);
175                 if (base) {
176                         u32 cache_id = readl(base + L2X0_CACHE_ID);
177
178                         if ((cache_id & 0xff0003c0) == 0x410000c0)
179                                 return base;
180
181                         iounmap(base);
182                 }
183         }
184
185         return NULL;
186 }
187
188 int gator_events_l2c310_init(void)
189 {
190         int i;
191
192         if (gator_cpuid() != CORTEX_A5 && gator_cpuid() != CORTEX_A9)
193                 return -1;
194
195         if (l2c310_addr == L2C310_ADDR_PROBE)
196                 l2c310_base = gator_events_l2c310_probe();
197         else if (l2c310_addr)
198                 l2c310_base = ioremap(l2c310_addr, SZ_4K);
199
200         if (!l2c310_base)
201                 return -1;
202
203         for (i = 0; i < L2C310_COUNTERS_NUM; i++) {
204                 l2c310_counters[i].enabled = 0;
205                 l2c310_counters[i].key = gator_events_get_key();
206         }
207
208         return gator_events_install(&gator_events_l2c310_interface);
209 }