gator: ARM DS-5.6 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_events_pl310.c
1 /**
2  * PL310 (L2 Cache Controller) event counters for gator
3  *
4  * Copyright (C) ARM Limited 2010-2011. 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 PL310_COUNTERS_NUM 2
19 static struct {
20         unsigned long enabled;
21         unsigned long event;
22         unsigned long key;
23 } pl310_counters[PL310_COUNTERS_NUM];
25 static int pl310_buffer[PL310_COUNTERS_NUM * 2];
27 static void __iomem *pl310_base;
31 static void gator_events_pl310_reset_counters(void)
32 {
33         u32 val = readl(pl310_base + L2X0_EVENT_CNT_CTRL);
35         val |= ((1 << PL310_COUNTERS_NUM) - 1) << 1;
37         writel(val, pl310_base + L2X0_EVENT_CNT_CTRL);
38 }
41 static int gator_events_pl310_create_files(struct super_block *sb,
42                 struct dentry *root)
43 {
44         int i;
46         for (i = 0; i < PL310_COUNTERS_NUM; i++) {
47                 char buf[16];
48                 struct dentry *dir;
50                 snprintf(buf, sizeof(buf), "PL310_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                                 &pl310_counters[i].enabled);
56                 gatorfs_create_ulong(sb, dir, "event",
57                                 &pl310_counters[i].event);
58                 gatorfs_create_ro_ulong(sb, dir, "key",
59                                 &pl310_counters[i].key);
60         }
62         return 0;
63 }
65 static int gator_events_pl310_start(void)
66 {
67         static const unsigned long l2x0_event_cntx_cfg[PL310_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 < PL310_COUNTERS_NUM; i++)
75                 writel((pl310_counters[i].event & 0xf) << 2,
76                                 pl310_base + l2x0_event_cntx_cfg[i]);
78         gator_events_pl310_reset_counters();
80         /* Event counter enable */
81         writel(1, pl310_base + L2X0_EVENT_CNT_CTRL);
83         return 0;
84 }
86 static void gator_events_pl310_stop(void)
87 {
88         /* Event counter disable */
89         writel(0, pl310_base + L2X0_EVENT_CNT_CTRL);
90 }
92 static int gator_events_pl310_read(int **buffer)
93 {
94         static const unsigned long l2x0_event_cntx_val[PL310_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 < PL310_COUNTERS_NUM; i++) {
105                 if (pl310_counters[i].enabled) {
106                         pl310_buffer[len++] = pl310_counters[i].key;
107                         pl310_buffer[len++] = readl(pl310_base +
108                                         l2x0_event_cntx_val[i]);
109                 }
110         }
111         
112         /* PL310 counters are saturating, not wrapping in case of overflow */
113         gator_events_pl310_reset_counters();
115         if (buffer)
116                 *buffer = pl310_buffer;
118         return len;
121 static struct gator_interface gator_events_pl310_interface = {
122         .create_files = gator_events_pl310_create_files,
123         .start = gator_events_pl310_start,
124         .stop = gator_events_pl310_stop,
125         .read = gator_events_pl310_read,
126 };
128 static void __maybe_unused gator_events_pl310_probe(unsigned long phys)
130         if (pl310_base)
131                 return;
133         pl310_base = ioremap(phys, SZ_4K);
134         if (pl310_base) {
135                 u32 cache_id = readl(pl310_base + L2X0_CACHE_ID);
137                 if ((cache_id & 0xff0003c0) != 0x410000c0) {
138                         iounmap(pl310_base);
139                         pl310_base = NULL;
140                 }
141         }
144 int gator_events_pl310_init(void)
146         int i;
148 #if defined(CONFIG_ARCH_EXYNOS4)
149         gator_events_pl310_probe(0xfe600000);
150 #endif
151 #if defined(CONFIG_ARCH_OMAP4)
152         gator_events_pl310_probe(0x48242000);
153 #endif
154 #if defined(CONFIG_ARCH_TEGRA)
155         gator_events_pl310_probe(0x50043000);
156 #endif
157 #if defined(CONFIG_ARCH_U8500)
158         gator_events_pl310_probe(0xa0412000);
159 #endif
160 #if defined(CONFIG_ARCH_VEXPRESS) && !defined(CONFIG_ARCH_VEXPRESS_CA15X4)
161         // A9x4 core tile (HBI-0191)
162         gator_events_pl310_probe(0x1e00a000);
163         // New memory map tiles
164         gator_events_pl310_probe(0x2c0f0000);
165 #endif
166         if (!pl310_base)
167                 return -1;
169         for (i = 0; i < PL310_COUNTERS_NUM; i++) {
170                 pl310_counters[i].enabled = 0;
171                 pl310_counters[i].key = gator_events_get_key();
172         }
174         return gator_events_install(&gator_events_pl310_interface);
176 gator_events_init(gator_events_pl310_init);