blob: ca6e0c6af8b3654af1874274c6f1dff03cba517b [file] [log] [blame]
Pratik Patel17f3b822011-11-21 12:41:47 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Pratik Patel7831c082011-06-08 21:44:37 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
Pratik Patelcf418622011-09-22 11:15:11 -070015#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/device.h>
Pratik Patel7831c082011-06-08 21:44:37 -070018#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/err.h>
21#include <linux/fs.h>
Pratik Patel7831c082011-06-08 21:44:37 -070022#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/smp.h>
Pratik Patel7831c082011-06-08 21:44:37 -070025#include <linux/wakelock.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070026#include <linux/pm_qos.h>
Pratik Patel6630ebe2012-03-06 16:44:22 -080027#include <linux/sysfs.h>
28#include <linux/stat.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080029#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080030#include <mach/socinfo.h>
Pratik Patel7831c082011-06-08 21:44:37 -070031
Pratik Patelb27a9352012-03-17 22:37:21 -070032#include "qdss-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070033
Pratik Patel492b3012012-03-06 14:22:30 -080034#define etm_writel(etm, cpu, val, off) \
35 __raw_writel((val), etm.base + (SZ_4K * cpu) + off)
36#define etm_readl(etm, cpu, off) \
37 __raw_readl(etm.base + (SZ_4K * cpu) + off)
Pratik Patel7831c082011-06-08 21:44:37 -070038
39/*
40 * Device registers:
41 * 0x000 - 0x2FC: Trace registers
42 * 0x300 - 0x314: Management registers
43 * 0x318 - 0xEFC: Trace registers
44 *
45 * Coresight registers
46 * 0xF00 - 0xF9C: Management registers
47 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
48 * Trace registers in PFTv1.1
49 * 0xFA8 - 0xFFC: Management registers
50 */
51
52/* Trace registers (0x000-0x2FC) */
53#define ETMCR (0x000)
54#define ETMCCR (0x004)
55#define ETMTRIGGER (0x008)
56#define ETMSR (0x010)
57#define ETMSCR (0x014)
58#define ETMTSSCR (0x018)
59#define ETMTEEVR (0x020)
60#define ETMTECR1 (0x024)
61#define ETMFFLR (0x02C)
62#define ETMACVRn(n) (0x040 + (n * 4))
63#define ETMACTRn(n) (0x080 + (n * 4))
64#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
65#define ETMCNTENRn(n) (0x150 + (n * 4))
66#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
67#define ETMCNTVRn(n) (0x170 + (n * 4))
68#define ETMSQ12EVR (0x180)
69#define ETMSQ21EVR (0x184)
70#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -080071#define ETMSQ31EVR (0x18C)
72#define ETMSQ32EVR (0x190)
73#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -070074#define ETMSQR (0x19C)
75#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
76#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
77#define ETMCIDCMR (0x1BC)
78#define ETMIMPSPEC0 (0x1C0)
79#define ETMIMPSPEC1 (0x1C4)
80#define ETMIMPSPEC2 (0x1C8)
81#define ETMIMPSPEC3 (0x1CC)
82#define ETMIMPSPEC4 (0x1D0)
83#define ETMIMPSPEC5 (0x1D4)
84#define ETMIMPSPEC6 (0x1D8)
85#define ETMIMPSPEC7 (0x1DC)
86#define ETMSYNCFR (0x1E0)
87#define ETMIDR (0x1E4)
88#define ETMCCER (0x1E8)
89#define ETMEXTINSELR (0x1EC)
90#define ETMTESSEICR (0x1F0)
91#define ETMEIBCR (0x1F4)
92#define ETMTSEVR (0x1F8)
93#define ETMAUXCR (0x1FC)
94#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -080095#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -070096/* Management registers (0x300-0x314) */
97#define ETMOSLAR (0x300)
98#define ETMOSLSR (0x304)
99#define ETMOSSRR (0x308)
100#define ETMPDCR (0x310)
101#define ETMPDSR (0x314)
102
Pratik Patel61de7302012-03-07 12:06:10 -0800103#define ETM_MAX_ADDR_CMP (16)
104#define ETM_MAX_CNTR (4)
105#define ETM_MAX_CTXID_CMP (3)
106
Pratik Patel6630ebe2012-03-06 16:44:22 -0800107#define ETM_MODE_EXCLUDE BIT(0)
108#define ETM_MODE_CYCACC BIT(1)
109#define ETM_MODE_STALL BIT(2)
110#define ETM_MODE_TIMESTAMP BIT(3)
111#define ETM_MODE_CTXID BIT(4)
112#define ETM_MODE_ALL (0x1F)
113
114#define ETM_EVENT_MASK (0x1FFFF)
115#define ETM_SYNC_MASK (0xFFF)
116#define ETM_ALL_MASK (0xFFFFFFFF)
117
118#define ETM_SEQ_STATE_MAX_VAL (0x2)
119
120enum {
121 ETM_ADDR_TYPE_NONE,
122 ETM_ADDR_TYPE_SINGLE,
123 ETM_ADDR_TYPE_RANGE,
124 ETM_ADDR_TYPE_START,
125 ETM_ADDR_TYPE_STOP,
126};
127
Pratik Patel492b3012012-03-06 14:22:30 -0800128#define ETM_LOCK(cpu) \
Pratik Patel7831c082011-06-08 21:44:37 -0700129do { \
130 mb(); \
Pratik Patel492b3012012-03-06 14:22:30 -0800131 etm_writel(etm, cpu, 0x0, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -0700132} while (0)
Pratik Patel492b3012012-03-06 14:22:30 -0800133#define ETM_UNLOCK(cpu) \
Pratik Patel7831c082011-06-08 21:44:37 -0700134do { \
Pratik Patel492b3012012-03-06 14:22:30 -0800135 etm_writel(etm, cpu, CS_UNLOCK_MAGIC, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -0700136 mb(); \
137} while (0)
138
Pratik Patel7831c082011-06-08 21:44:37 -0700139
Pratik Patel6630ebe2012-03-06 16:44:22 -0800140#ifdef MODULE_PARAM_PREFIX
141#undef MODULE_PARAM_PREFIX
142#endif
143#define MODULE_PARAM_PREFIX "qdss."
144
Pratik Patel29cba152012-01-03 11:40:26 -0800145#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel61de7302012-03-07 12:06:10 -0800146static int etm_boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800147#else
Pratik Patel61de7302012-03-07 12:06:10 -0800148static int etm_boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800149#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700150module_param_named(
Pratik Patel61de7302012-03-07 12:06:10 -0800151 etm_boot_enable, etm_boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700152);
153
Pratik Patel492b3012012-03-06 14:22:30 -0800154struct etm_ctx {
Pratik Patel7831c082011-06-08 21:44:37 -0700155 void __iomem *base;
Pratik Patel61de7302012-03-07 12:06:10 -0800156 bool enabled;
Pratik Patel7831c082011-06-08 21:44:37 -0700157 struct wake_lock wake_lock;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700158 struct pm_qos_request qos_req;
Pratik Patele10a77c2012-03-20 10:35:16 -0700159 struct qdss_source *src;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800160 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700161 struct device *dev;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800162 struct kobject *kobj;
Pratik Patel61de7302012-03-07 12:06:10 -0800163 uint8_t arch;
164 uint8_t nr_addr_cmp;
165 uint8_t nr_cntr;
166 uint8_t nr_ext_inp;
167 uint8_t nr_ext_out;
168 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800169 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800170 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800171 uint32_t ctrl;
172 uint32_t trigger_event;
173 uint32_t startstop_ctrl;
174 uint32_t enable_event;
175 uint32_t enable_ctrl1;
176 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800177 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800178 uint32_t addr_val[ETM_MAX_ADDR_CMP];
179 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800180 uint32_t addr_type[ETM_MAX_ADDR_CMP];
181 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800182 uint32_t cntr_rld_val[ETM_MAX_CNTR];
183 uint32_t cntr_event[ETM_MAX_CNTR];
184 uint32_t cntr_rld_event[ETM_MAX_CNTR];
185 uint32_t cntr_val[ETM_MAX_CNTR];
186 uint32_t seq_12_event;
187 uint32_t seq_21_event;
188 uint32_t seq_23_event;
189 uint32_t seq_31_event;
190 uint32_t seq_32_event;
191 uint32_t seq_13_event;
192 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800193 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800194 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
195 uint32_t ctxid_mask;
196 uint32_t sync_freq;
197 uint32_t timestamp_event;
Pratik Patel7831c082011-06-08 21:44:37 -0700198};
199
Pratik Patel61de7302012-03-07 12:06:10 -0800200static struct etm_ctx etm = {
Pratik Patel61de7302012-03-07 12:06:10 -0800201 .trigger_event = 0x406F,
202 .enable_event = 0x6F,
Pratik Pateld30deda2012-02-01 14:40:55 -0800203 .enable_ctrl1 = 0x1,
Pratik Patel61de7302012-03-07 12:06:10 -0800204 .fifofull_level = 0x28,
Pratik Pateld30deda2012-02-01 14:40:55 -0800205 .addr_val = {(uint32_t) _stext, (uint32_t) _etext},
206 .addr_type = {ETM_ADDR_TYPE_RANGE, ETM_ADDR_TYPE_RANGE},
Pratik Patel61de7302012-03-07 12:06:10 -0800207 .cntr_event = {[0 ... (ETM_MAX_CNTR - 1)] = 0x406F},
208 .cntr_rld_event = {[0 ... (ETM_MAX_CNTR - 1)] = 0x406F},
209 .seq_12_event = 0x406F,
210 .seq_21_event = 0x406F,
211 .seq_23_event = 0x406F,
212 .seq_31_event = 0x406F,
213 .seq_32_event = 0x406F,
214 .seq_13_event = 0x406F,
215 .sync_freq = 0x80,
216 .timestamp_event = 0x406F,
217};
Pratik Patel7831c082011-06-08 21:44:37 -0700218
Pratik Patel7831c082011-06-08 21:44:37 -0700219
Pratik Patel17f3b822011-11-21 12:41:47 -0800220/* ETM clock is derived from the processor clock and gets enabled on a
221 * logical OR of below items on Krait (pass2 onwards):
222 * 1.CPMR[ETMCLKEN] is 1
223 * 2.ETMCR[PD] is 0
224 * 3.ETMPDCR[PU] is 1
225 * 4.Reset is asserted (core or debug)
226 * 5.APB memory mapped requests (eg. EDAP access)
227 *
228 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
229 * enables
230 *
231 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
232 * clock vote in the driver and the save-restore code uses 1. above
233 * for its vote
234 */
Pratik Patel61de7302012-03-07 12:06:10 -0800235static void etm_set_pwrdwn(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700236{
237 uint32_t etmcr;
238
Pratik Patel492b3012012-03-06 14:22:30 -0800239 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700240 etmcr |= BIT(0);
Pratik Patel492b3012012-03-06 14:22:30 -0800241 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700242}
243
Pratik Patel61de7302012-03-07 12:06:10 -0800244static void etm_clr_pwrdwn(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700245{
246 uint32_t etmcr;
247
Pratik Patel492b3012012-03-06 14:22:30 -0800248 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700249 etmcr &= ~BIT(0);
Pratik Patel492b3012012-03-06 14:22:30 -0800250 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700251}
252
Pratik Patel492b3012012-03-06 14:22:30 -0800253static void etm_set_prog(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700254{
255 uint32_t etmcr;
256 int count;
257
Pratik Patel492b3012012-03-06 14:22:30 -0800258 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700259 etmcr |= BIT(10);
Pratik Patel492b3012012-03-06 14:22:30 -0800260 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700261
Pratik Patel492b3012012-03-06 14:22:30 -0800262 for (count = TIMEOUT_US; BVAL(etm_readl(etm, cpu, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700263 && count > 0; count--)
264 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800265 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
266 etm_readl(etm, cpu, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700267}
268
Pratik Patel61de7302012-03-07 12:06:10 -0800269static void etm_clr_prog(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700270{
271 uint32_t etmcr;
272 int count;
273
Pratik Patel492b3012012-03-06 14:22:30 -0800274 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700275 etmcr &= ~BIT(10);
Pratik Patel492b3012012-03-06 14:22:30 -0800276 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700277
Pratik Patel492b3012012-03-06 14:22:30 -0800278 for (count = TIMEOUT_US; BVAL(etm_readl(etm, cpu, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700279 && count > 0; count--)
280 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800281 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
282 etm_readl(etm, cpu, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700283}
284
Pratik Patel61de7302012-03-07 12:06:10 -0800285static void __etm_enable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700286{
Pratik Patel17f3b822011-11-21 12:41:47 -0800287 int i;
Pratik Patel7831c082011-06-08 21:44:37 -0700288
Pratik Patel492b3012012-03-06 14:22:30 -0800289 ETM_UNLOCK(cpu);
Pratik Patel17f3b822011-11-21 12:41:47 -0800290 /* Vote for ETM power/clock enable */
Pratik Patel61de7302012-03-07 12:06:10 -0800291 etm_clr_pwrdwn(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -0800292 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700293
Pratik Patel61de7302012-03-07 12:06:10 -0800294 etm_writel(etm, cpu, etm.ctrl | BIT(10), ETMCR);
295 etm_writel(etm, cpu, etm.trigger_event, ETMTRIGGER);
296 etm_writel(etm, cpu, etm.startstop_ctrl, ETMTSSCR);
297 etm_writel(etm, cpu, etm.enable_event, ETMTEEVR);
298 etm_writel(etm, cpu, etm.enable_ctrl1, ETMTECR1);
299 etm_writel(etm, cpu, etm.fifofull_level, ETMFFLR);
300 for (i = 0; i < etm.nr_addr_cmp; i++) {
301 etm_writel(etm, cpu, etm.addr_val[i], ETMACVRn(i));
302 etm_writel(etm, cpu, etm.addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700303 }
Pratik Patel61de7302012-03-07 12:06:10 -0800304 for (i = 0; i < etm.nr_cntr; i++) {
305 etm_writel(etm, cpu, etm.cntr_rld_val[i], ETMCNTRLDVRn(i));
306 etm_writel(etm, cpu, etm.cntr_event[i], ETMCNTENRn(i));
307 etm_writel(etm, cpu, etm.cntr_rld_event[i], ETMCNTRLDEVRn(i));
308 etm_writel(etm, cpu, etm.cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800309 }
Pratik Patel61de7302012-03-07 12:06:10 -0800310 etm_writel(etm, cpu, etm.seq_12_event, ETMSQ12EVR);
311 etm_writel(etm, cpu, etm.seq_21_event, ETMSQ21EVR);
312 etm_writel(etm, cpu, etm.seq_23_event, ETMSQ23EVR);
313 etm_writel(etm, cpu, etm.seq_31_event, ETMSQ31EVR);
314 etm_writel(etm, cpu, etm.seq_32_event, ETMSQ32EVR);
315 etm_writel(etm, cpu, etm.seq_13_event, ETMSQ13EVR);
316 etm_writel(etm, cpu, etm.seq_curr_state, ETMSQR);
317 for (i = 0; i < etm.nr_ext_out; i++)
318 etm_writel(etm, cpu, 0x0000406F, ETMEXTOUTEVRn(i));
319 for (i = 0; i < etm.nr_ctxid_cmp; i++)
320 etm_writel(etm, cpu, etm.ctxid_val[i], ETMCIDCVRn(i));
321 etm_writel(etm, cpu, etm.ctxid_mask, ETMCIDCMR);
322 etm_writel(etm, cpu, etm.sync_freq, ETMSYNCFR);
323 etm_writel(etm, cpu, 0x00000000, ETMEXTINSELR);
324 etm_writel(etm, cpu, etm.timestamp_event, ETMTSEVR);
325 etm_writel(etm, cpu, 0x00000000, ETMAUXCR);
Pratik Patel492b3012012-03-06 14:22:30 -0800326 etm_writel(etm, cpu, cpu+1, ETMTRACEIDR);
Pratik Patel61de7302012-03-07 12:06:10 -0800327 etm_writel(etm, cpu, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800328
Pratik Patel61de7302012-03-07 12:06:10 -0800329 etm_clr_prog(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -0800330 ETM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700331}
332
Pratik Patel61de7302012-03-07 12:06:10 -0800333static int etm_enable(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700334{
Pratik Patel17f3b822011-11-21 12:41:47 -0800335 int ret, cpu;
Pratik Patel7831c082011-06-08 21:44:37 -0700336
Pratik Patel61de7302012-03-07 12:06:10 -0800337 if (etm.enabled) {
338 dev_err(etm.dev, "ETM tracing already enabled\n");
339 ret = -EPERM;
340 goto err;
341 }
342
Pratik Patel492b3012012-03-06 14:22:30 -0800343 wake_lock(&etm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700344 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700345 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700346 *
347 * we rely on the user to prevent hotplug on/off racing with this
348 * operation and to ensure cores where trace is expected to be turned
349 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700350 */
Pratik Patel492b3012012-03-06 14:22:30 -0800351 pm_qos_update_request(&etm.qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700352
Pratik Patele10a77c2012-03-20 10:35:16 -0700353 ret = qdss_enable(etm.src);
354 if (ret)
355 goto err_qdss;
356
Pratik Patel17f3b822011-11-21 12:41:47 -0800357 for_each_online_cpu(cpu)
Pratik Patel61de7302012-03-07 12:06:10 -0800358 __etm_enable(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700359
Pratik Patel61de7302012-03-07 12:06:10 -0800360 etm.enabled = true;
Pratik Patel7831c082011-06-08 21:44:37 -0700361
Pratik Patel492b3012012-03-06 14:22:30 -0800362 pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
363 wake_unlock(&etm.wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700364
Pratik Patel61de7302012-03-07 12:06:10 -0800365 dev_info(etm.dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700366 return 0;
Pratik Patele10a77c2012-03-20 10:35:16 -0700367
368err_qdss:
369 pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
370 wake_unlock(&etm.wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800371err:
372 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700373}
374
Pratik Patel61de7302012-03-07 12:06:10 -0800375static void __etm_disable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700376{
Pratik Patel492b3012012-03-06 14:22:30 -0800377 ETM_UNLOCK(cpu);
378 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700379
Pratik Patel17f3b822011-11-21 12:41:47 -0800380 /* program trace enable to low by using always false event */
Pratik Patel492b3012012-03-06 14:22:30 -0800381 etm_writel(etm, cpu, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700382
Pratik Patel17f3b822011-11-21 12:41:47 -0800383 /* Vote for ETM power/clock disable */
Pratik Patel61de7302012-03-07 12:06:10 -0800384 etm_set_pwrdwn(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -0800385 ETM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700386}
387
Pratik Patel61de7302012-03-07 12:06:10 -0800388static int etm_disable(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700389{
Pratik Patel61de7302012-03-07 12:06:10 -0800390 int ret, cpu;
391
392 if (!etm.enabled) {
393 dev_err(etm.dev, "ETM tracing already disabled\n");
394 ret = -EPERM;
395 goto err;
396 }
Pratik Patel17f3b822011-11-21 12:41:47 -0800397
Pratik Patel492b3012012-03-06 14:22:30 -0800398 wake_lock(&etm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700399 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700400 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700401 *
402 * we rely on the user to prevent hotplug on/off racing with this
403 * operation and to ensure cores where trace is expected to be turned
404 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700405 */
Pratik Patel492b3012012-03-06 14:22:30 -0800406 pm_qos_update_request(&etm.qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700407
Pratik Patel17f3b822011-11-21 12:41:47 -0800408 for_each_online_cpu(cpu)
Pratik Patel61de7302012-03-07 12:06:10 -0800409 __etm_disable(cpu);
Pratik Patele10a77c2012-03-20 10:35:16 -0700410
411 qdss_disable(etm.src);
Pratik Patel7831c082011-06-08 21:44:37 -0700412
Pratik Patel61de7302012-03-07 12:06:10 -0800413 etm.enabled = false;
Pratik Patel7831c082011-06-08 21:44:37 -0700414
Pratik Patel492b3012012-03-06 14:22:30 -0800415 pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
416 wake_unlock(&etm.wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700417
Pratik Patel61de7302012-03-07 12:06:10 -0800418 dev_info(etm.dev, "ETM tracing disabled\n");
419 return 0;
420err:
421 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700422}
423
Pratik Patel17f3b822011-11-21 12:41:47 -0800424/* Memory mapped writes to clear os lock not supported */
Pratik Patel492b3012012-03-06 14:22:30 -0800425static void etm_os_unlock(void *unused)
Pratik Patel17f3b822011-11-21 12:41:47 -0800426{
427 unsigned long value = 0x0;
428
429 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
430 asm("isb\n\t");
431}
432
Pratik Patel6630ebe2012-03-06 16:44:22 -0800433#define ETM_STORE(__name, mask) \
434static ssize_t __name##_store(struct kobject *kobj, \
435 struct kobj_attribute *attr, \
436 const char *buf, size_t n) \
437{ \
438 unsigned long val; \
439 \
440 if (sscanf(buf, "%lx", &val) != 1) \
441 return -EINVAL; \
442 \
443 etm.__name = val & mask; \
444 return n; \
445}
446
447#define ETM_SHOW(__name) \
448static ssize_t __name##_show(struct kobject *kobj, \
449 struct kobj_attribute *attr, \
450 char *buf) \
451{ \
452 unsigned long val = etm.__name; \
453 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); \
454}
455
456#define ETM_ATTR(__name) \
457static struct kobj_attribute __name##_attr = \
458 __ATTR(__name, S_IRUGO | S_IWUSR, __name##_show, __name##_store)
459#define ETM_ATTR_RO(__name) \
460static struct kobj_attribute __name##_attr = \
461 __ATTR(__name, S_IRUGO, __name##_show, NULL)
462
463static ssize_t enabled_store(struct kobject *kobj,
464 struct kobj_attribute *attr,
465 const char *buf, size_t n)
466{
467 int ret = 0;
468 unsigned long val;
469
470 if (sscanf(buf, "%lx", &val) != 1)
471 return -EINVAL;
472
473 mutex_lock(&etm.mutex);
474 if (val)
475 ret = etm_enable();
476 else
477 ret = etm_disable();
478 mutex_unlock(&etm.mutex);
479
480 if (ret)
481 return ret;
482 return n;
483}
484ETM_SHOW(enabled);
485ETM_ATTR(enabled);
486
487ETM_SHOW(nr_addr_cmp);
488ETM_ATTR_RO(nr_addr_cmp);
489ETM_SHOW(nr_cntr);
490ETM_ATTR_RO(nr_cntr);
491ETM_SHOW(nr_ctxid_cmp);
492ETM_ATTR_RO(nr_ctxid_cmp);
493
Pratik Pateld30deda2012-02-01 14:40:55 -0800494/* Reset to trace everything i.e. exclude nothing. */
495static ssize_t reset_store(struct kobject *kobj,
496 struct kobj_attribute *attr,
497 const char *buf, size_t n)
498{
499 int i;
500 unsigned long val;
501
502 if (sscanf(buf, "%lx", &val) != 1)
503 return -EINVAL;
504
505 mutex_lock(&etm.mutex);
506 if (val) {
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800507 etm.mode = ETM_MODE_EXCLUDE;
508 etm.ctrl = 0x0;
509 if (cpu_is_krait_v1()) {
510 etm.mode |= ETM_MODE_CYCACC;
511 etm.ctrl |= BIT(12);
512 }
Pratik Pateld30deda2012-02-01 14:40:55 -0800513 etm.trigger_event = 0x406F;
514 etm.startstop_ctrl = 0x0;
515 etm.enable_event = 0x6F;
516 etm.enable_ctrl1 = 0x1000000;
517 etm.fifofull_level = 0x28;
518 etm.addr_idx = 0x0;
519 for (i = 0; i < etm.nr_addr_cmp; i++) {
520 etm.addr_val[i] = 0x0;
521 etm.addr_acctype[i] = 0x0;
522 etm.addr_type[i] = ETM_ADDR_TYPE_NONE;
523 }
524 etm.cntr_idx = 0x0;
525 for (i = 0; i < etm.nr_cntr; i++) {
526 etm.cntr_rld_val[i] = 0x0;
527 etm.cntr_event[i] = 0x406F;
528 etm.cntr_rld_event[i] = 0x406F;
529 etm.cntr_val[i] = 0x0;
530 }
531 etm.seq_12_event = 0x406F;
532 etm.seq_21_event = 0x406F;
533 etm.seq_23_event = 0x406F;
534 etm.seq_31_event = 0x406F;
535 etm.seq_32_event = 0x406F;
536 etm.seq_13_event = 0x406F;
537 etm.seq_curr_state = 0x0;
538 etm.ctxid_idx = 0x0;
539 for (i = 0; i < etm.nr_ctxid_cmp; i++)
540 etm.ctxid_val[i] = 0x0;
541 etm.ctxid_mask = 0x0;
542 etm.sync_freq = 0x80;
543 etm.timestamp_event = 0x406F;
544 }
545 mutex_unlock(&etm.mutex);
546 return n;
547}
548ETM_SHOW(reset);
549ETM_ATTR(reset);
550
Pratik Patel6630ebe2012-03-06 16:44:22 -0800551static ssize_t mode_store(struct kobject *kobj,
552 struct kobj_attribute *attr,
553 const char *buf, size_t n)
554{
555 unsigned long val;
556
557 if (sscanf(buf, "%lx", &val) != 1)
558 return -EINVAL;
559
560 mutex_lock(&etm.mutex);
561 etm.mode = val & ETM_MODE_ALL;
562
563 if (etm.mode & ETM_MODE_EXCLUDE)
564 etm.enable_ctrl1 |= BIT(24);
565 else
566 etm.enable_ctrl1 &= ~BIT(24);
567
568 if (etm.mode & ETM_MODE_CYCACC)
569 etm.ctrl |= BIT(12);
570 else
571 etm.ctrl &= ~BIT(12);
572
573 if (etm.mode & ETM_MODE_STALL)
574 etm.ctrl |= BIT(7);
575 else
576 etm.ctrl &= ~BIT(7);
577
578 if (etm.mode & ETM_MODE_TIMESTAMP)
579 etm.ctrl |= BIT(28);
580 else
581 etm.ctrl &= ~BIT(28);
582 if (etm.mode & ETM_MODE_CTXID)
583 etm.ctrl |= (BIT(14) | BIT(15));
584 else
585 etm.ctrl &= ~(BIT(14) | BIT(15));
586 mutex_unlock(&etm.mutex);
587
588 return n;
589}
590ETM_SHOW(mode);
591ETM_ATTR(mode);
592
593ETM_STORE(trigger_event, ETM_EVENT_MASK);
594ETM_SHOW(trigger_event);
595ETM_ATTR(trigger_event);
596
597ETM_STORE(enable_event, ETM_EVENT_MASK);
598ETM_SHOW(enable_event);
599ETM_ATTR(enable_event);
600
601ETM_STORE(fifofull_level, ETM_ALL_MASK);
602ETM_SHOW(fifofull_level);
603ETM_ATTR(fifofull_level);
604
605static ssize_t addr_idx_store(struct kobject *kobj,
606 struct kobj_attribute *attr,
607 const char *buf, size_t n)
608{
609 unsigned long val;
610
611 if (sscanf(buf, "%lx", &val) != 1)
612 return -EINVAL;
613 if (val >= etm.nr_addr_cmp)
614 return -EINVAL;
615
616 /* Use mutex to ensure index doesn't change while it gets dereferenced
617 * multiple times within a mutex block elsewhere.
618 */
619 mutex_lock(&etm.mutex);
620 etm.addr_idx = val;
621 mutex_unlock(&etm.mutex);
622 return n;
623}
624ETM_SHOW(addr_idx);
625ETM_ATTR(addr_idx);
626
Pratik Patel6630ebe2012-03-06 16:44:22 -0800627static ssize_t addr_single_store(struct kobject *kobj,
628 struct kobj_attribute *attr,
629 const char *buf, size_t n)
630{
631 unsigned long val;
632 uint8_t idx;
633
634 if (sscanf(buf, "%lx", &val) != 1)
635 return -EINVAL;
636
637 mutex_lock(&etm.mutex);
638 idx = etm.addr_idx;
639 if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
640 etm.addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
641 mutex_unlock(&etm.mutex);
642 return -EPERM;
643 }
644
645 etm.addr_val[idx] = val;
646 etm.addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800647 mutex_unlock(&etm.mutex);
648 return n;
649}
650static ssize_t addr_single_show(struct kobject *kobj,
651 struct kobj_attribute *attr,
652 char *buf)
653{
654 unsigned long val;
655 uint8_t idx;
656
657 mutex_lock(&etm.mutex);
658 idx = etm.addr_idx;
659 if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
660 etm.addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
661 mutex_unlock(&etm.mutex);
662 return -EPERM;
663 }
664
665 val = etm.addr_val[idx];
666 mutex_unlock(&etm.mutex);
667 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
668}
669ETM_ATTR(addr_single);
670
671static ssize_t addr_range_store(struct kobject *kobj,
672 struct kobj_attribute *attr,
673 const char *buf, size_t n)
674{
675 unsigned long val1, val2;
676 uint8_t idx;
677
678 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
679 return -EINVAL;
680 /* lower address comparator cannot have a higher address value */
681 if (val1 > val2)
682 return -EINVAL;
683
684 mutex_lock(&etm.mutex);
685 idx = etm.addr_idx;
686 if (idx % 2 != 0) {
687 mutex_unlock(&etm.mutex);
688 return -EPERM;
689 }
690 if (!((etm.addr_type[idx] == ETM_ADDR_TYPE_NONE &&
691 etm.addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
692 (etm.addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
693 etm.addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
694 mutex_unlock(&etm.mutex);
695 return -EPERM;
696 }
697
698 etm.addr_val[idx] = val1;
699 etm.addr_type[idx] = ETM_ADDR_TYPE_RANGE;
700 etm.addr_val[idx + 1] = val2;
701 etm.addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
702 etm.enable_ctrl1 |= (1 << (idx/2));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800703 mutex_unlock(&etm.mutex);
704 return n;
705}
706static ssize_t addr_range_show(struct kobject *kobj,
707 struct kobj_attribute *attr,
708 char *buf)
709{
710 unsigned long val1, val2;
711 uint8_t idx;
712
713 mutex_lock(&etm.mutex);
714 idx = etm.addr_idx;
715 if (idx % 2 != 0) {
716 mutex_unlock(&etm.mutex);
717 return -EPERM;
718 }
719 if (!((etm.addr_type[idx] == ETM_ADDR_TYPE_NONE &&
720 etm.addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
721 (etm.addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
722 etm.addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
723 mutex_unlock(&etm.mutex);
724 return -EPERM;
725 }
726
727 val1 = etm.addr_val[idx];
728 val2 = etm.addr_val[idx + 1];
729 mutex_unlock(&etm.mutex);
730 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
731}
732ETM_ATTR(addr_range);
733
734static ssize_t addr_start_store(struct kobject *kobj,
735 struct kobj_attribute *attr,
736 const char *buf, size_t n)
737{
738 unsigned long val;
739 uint8_t idx;
740
741 if (sscanf(buf, "%lx", &val) != 1)
742 return -EINVAL;
743
744 mutex_lock(&etm.mutex);
745 idx = etm.addr_idx;
746 if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
747 etm.addr_type[idx] == ETM_ADDR_TYPE_START)) {
748 mutex_unlock(&etm.mutex);
749 return -EPERM;
750 }
751
752 etm.addr_val[idx] = val;
753 etm.addr_type[idx] = ETM_ADDR_TYPE_START;
754 etm.startstop_ctrl |= (1 << idx);
755 etm.enable_ctrl1 |= BIT(25);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800756 mutex_unlock(&etm.mutex);
757 return n;
758}
759static ssize_t addr_start_show(struct kobject *kobj,
760 struct kobj_attribute *attr,
761 char *buf)
762{
763 unsigned long val;
764 uint8_t idx;
765
766 mutex_lock(&etm.mutex);
767 idx = etm.addr_idx;
768 if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
769 etm.addr_type[idx] == ETM_ADDR_TYPE_START)) {
770 mutex_unlock(&etm.mutex);
771 return -EPERM;
772 }
773
774 val = etm.addr_val[idx];
775 mutex_unlock(&etm.mutex);
776 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
777}
778ETM_ATTR(addr_start);
779
780static ssize_t addr_stop_store(struct kobject *kobj,
781 struct kobj_attribute *attr,
782 const char *buf, size_t n)
783{
784 unsigned long val;
785 uint8_t idx;
786
787 if (sscanf(buf, "%lx", &val) != 1)
788 return -EINVAL;
789
790 mutex_lock(&etm.mutex);
791 idx = etm.addr_idx;
792 if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
793 etm.addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
794 mutex_unlock(&etm.mutex);
795 return -EPERM;
796 }
797
798 etm.addr_val[idx] = val;
799 etm.addr_type[idx] = ETM_ADDR_TYPE_STOP;
800 etm.startstop_ctrl |= (1 << (idx + 16));
801 etm.enable_ctrl1 |= BIT(25);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800802 mutex_unlock(&etm.mutex);
803 return n;
804}
805static ssize_t addr_stop_show(struct kobject *kobj,
806 struct kobj_attribute *attr,
807 char *buf)
808{
809 unsigned long val;
810 uint8_t idx;
811
812 mutex_lock(&etm.mutex);
813 idx = etm.addr_idx;
814 if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
815 etm.addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
816 mutex_unlock(&etm.mutex);
817 return -EPERM;
818 }
819
820 val = etm.addr_val[idx];
821 mutex_unlock(&etm.mutex);
822 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
823}
824ETM_ATTR(addr_stop);
825
826static ssize_t addr_acctype_store(struct kobject *kobj,
827 struct kobj_attribute *attr,
828 const char *buf, size_t n)
829{
830 unsigned long val;
831
832 if (sscanf(buf, "%lx", &val) != 1)
833 return -EINVAL;
834
835 mutex_lock(&etm.mutex);
836 etm.addr_acctype[etm.addr_idx] = val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800837 mutex_unlock(&etm.mutex);
838 return n;
839}
840static ssize_t addr_acctype_show(struct kobject *kobj,
841 struct kobj_attribute *attr,
842 char *buf)
843{
844 unsigned long val;
845
846 mutex_lock(&etm.mutex);
847 val = etm.addr_acctype[etm.addr_idx];
848 mutex_unlock(&etm.mutex);
849 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
850}
851ETM_ATTR(addr_acctype);
852
853static ssize_t cntr_idx_store(struct kobject *kobj,
854 struct kobj_attribute *attr,
855 const char *buf, size_t n)
856{
857 unsigned long val;
858
859 if (sscanf(buf, "%lx", &val) != 1)
860 return -EINVAL;
861 if (val >= etm.nr_cntr)
862 return -EINVAL;
863
864 /* Use mutex to ensure index doesn't change while it gets dereferenced
865 * multiple times within a mutex block elsewhere.
866 */
867 mutex_lock(&etm.mutex);
868 etm.cntr_idx = val;
869 mutex_unlock(&etm.mutex);
870 return n;
871}
872ETM_SHOW(cntr_idx);
873ETM_ATTR(cntr_idx);
874
875static ssize_t cntr_rld_val_store(struct kobject *kobj,
876 struct kobj_attribute *attr,
877 const char *buf, size_t n)
878{
879 unsigned long val;
880
881 if (sscanf(buf, "%lx", &val) != 1)
882 return -EINVAL;
883
884 mutex_lock(&etm.mutex);
885 etm.cntr_rld_val[etm.cntr_idx] = val;
886 mutex_unlock(&etm.mutex);
887 return n;
888}
889static ssize_t cntr_rld_val_show(struct kobject *kobj,
890 struct kobj_attribute *attr,
891 char *buf)
892{
893 unsigned long val;
894 mutex_lock(&etm.mutex);
895 val = etm.cntr_rld_val[etm.cntr_idx];
896 mutex_unlock(&etm.mutex);
897 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
898}
899ETM_ATTR(cntr_rld_val);
900
901static ssize_t cntr_event_store(struct kobject *kobj,
902 struct kobj_attribute *attr,
903 const char *buf, size_t n)
904{
905 unsigned long val;
906
907 if (sscanf(buf, "%lx", &val) != 1)
908 return -EINVAL;
909
910 mutex_lock(&etm.mutex);
911 etm.cntr_event[etm.cntr_idx] = val & ETM_EVENT_MASK;
912 mutex_unlock(&etm.mutex);
913 return n;
914}
915static ssize_t cntr_event_show(struct kobject *kobj,
916 struct kobj_attribute *attr,
917 char *buf)
918{
919 unsigned long val;
920
921 mutex_lock(&etm.mutex);
922 val = etm.cntr_event[etm.cntr_idx];
923 mutex_unlock(&etm.mutex);
924 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
925}
926ETM_ATTR(cntr_event);
927
928static ssize_t cntr_rld_event_store(struct kobject *kobj,
929 struct kobj_attribute *attr,
930 const char *buf, size_t n)
931{
932 unsigned long val;
933
934 if (sscanf(buf, "%lx", &val) != 1)
935 return -EINVAL;
936
937 mutex_lock(&etm.mutex);
938 etm.cntr_rld_event[etm.cntr_idx] = val & ETM_EVENT_MASK;
939 mutex_unlock(&etm.mutex);
940 return n;
941}
942static ssize_t cntr_rld_event_show(struct kobject *kobj,
943 struct kobj_attribute *attr,
944 char *buf)
945{
946 unsigned long val;
947
948 mutex_lock(&etm.mutex);
949 val = etm.cntr_rld_event[etm.cntr_idx];
950 mutex_unlock(&etm.mutex);
951 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
952}
953ETM_ATTR(cntr_rld_event);
954
955static ssize_t cntr_val_store(struct kobject *kobj,
956 struct kobj_attribute *attr,
957 const char *buf, size_t n)
958{
959 unsigned long val;
960
961 if (sscanf(buf, "%lx", &val) != 1)
962 return -EINVAL;
963
964 mutex_lock(&etm.mutex);
965 etm.cntr_val[etm.cntr_idx] = val;
966 mutex_unlock(&etm.mutex);
967 return n;
968}
969static ssize_t cntr_val_show(struct kobject *kobj,
970 struct kobj_attribute *attr,
971 char *buf)
972{
973 unsigned long val;
974
975 mutex_lock(&etm.mutex);
976 val = etm.cntr_val[etm.cntr_idx];
977 mutex_unlock(&etm.mutex);
978 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
979}
980ETM_ATTR(cntr_val);
981
982ETM_STORE(seq_12_event, ETM_EVENT_MASK);
983ETM_SHOW(seq_12_event);
984ETM_ATTR(seq_12_event);
985
986ETM_STORE(seq_21_event, ETM_EVENT_MASK);
987ETM_SHOW(seq_21_event);
988ETM_ATTR(seq_21_event);
989
990ETM_STORE(seq_23_event, ETM_EVENT_MASK);
991ETM_SHOW(seq_23_event);
992ETM_ATTR(seq_23_event);
993
994ETM_STORE(seq_31_event, ETM_EVENT_MASK);
995ETM_SHOW(seq_31_event);
996ETM_ATTR(seq_31_event);
997
998ETM_STORE(seq_32_event, ETM_EVENT_MASK);
999ETM_SHOW(seq_32_event);
1000ETM_ATTR(seq_32_event);
1001
1002ETM_STORE(seq_13_event, ETM_EVENT_MASK);
1003ETM_SHOW(seq_13_event);
1004ETM_ATTR(seq_13_event);
1005
1006static ssize_t seq_curr_state_store(struct kobject *kobj,
1007 struct kobj_attribute *attr,
1008 const char *buf, size_t n)
1009{
1010 unsigned long val;
1011
1012 if (sscanf(buf, "%lx", &val) != 1)
1013 return -EINVAL;
1014 if (val > ETM_SEQ_STATE_MAX_VAL)
1015 return -EINVAL;
1016
1017 etm.seq_curr_state = val;
1018 return n;
1019}
1020ETM_SHOW(seq_curr_state);
1021ETM_ATTR(seq_curr_state);
1022
1023static ssize_t ctxid_idx_store(struct kobject *kobj,
1024 struct kobj_attribute *attr,
1025 const char *buf, size_t n)
1026{
1027 unsigned long val;
1028
1029 if (sscanf(buf, "%lx", &val) != 1)
1030 return -EINVAL;
1031 if (val >= etm.nr_ctxid_cmp)
1032 return -EINVAL;
1033
1034 /* Use mutex to ensure index doesn't change while it gets dereferenced
1035 * multiple times within a mutex block elsewhere.
1036 */
1037 mutex_lock(&etm.mutex);
1038 etm.ctxid_idx = val;
1039 mutex_unlock(&etm.mutex);
1040 return n;
1041}
1042ETM_SHOW(ctxid_idx);
1043ETM_ATTR(ctxid_idx);
1044
1045static ssize_t ctxid_val_store(struct kobject *kobj,
1046 struct kobj_attribute *attr,
1047 const char *buf, size_t n)
1048{
1049 unsigned long val;
1050
1051 if (sscanf(buf, "%lx", &val) != 1)
1052 return -EINVAL;
1053
1054 mutex_lock(&etm.mutex);
1055 etm.ctxid_val[etm.ctxid_idx] = val;
1056 mutex_unlock(&etm.mutex);
1057 return n;
1058}
1059static ssize_t ctxid_val_show(struct kobject *kobj,
1060 struct kobj_attribute *attr,
1061 char *buf)
1062{
1063 unsigned long val;
1064
1065 mutex_lock(&etm.mutex);
1066 val = etm.ctxid_val[etm.ctxid_idx];
1067 mutex_unlock(&etm.mutex);
1068 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1069}
1070ETM_ATTR(ctxid_val);
1071
1072ETM_STORE(ctxid_mask, ETM_ALL_MASK);
1073ETM_SHOW(ctxid_mask);
1074ETM_ATTR(ctxid_mask);
1075
1076ETM_STORE(sync_freq, ETM_SYNC_MASK);
1077ETM_SHOW(sync_freq);
1078ETM_ATTR(sync_freq);
1079
1080ETM_STORE(timestamp_event, ETM_EVENT_MASK);
1081ETM_SHOW(timestamp_event);
1082ETM_ATTR(timestamp_event);
1083
1084static struct attribute *etm_attrs[] = {
1085 &nr_addr_cmp_attr.attr,
1086 &nr_cntr_attr.attr,
1087 &nr_ctxid_cmp_attr.attr,
Pratik Pateld30deda2012-02-01 14:40:55 -08001088 &reset_attr.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001089 &mode_attr.attr,
1090 &trigger_event_attr.attr,
1091 &enable_event_attr.attr,
1092 &fifofull_level_attr.attr,
1093 &addr_idx_attr.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001094 &addr_single_attr.attr,
1095 &addr_range_attr.attr,
1096 &addr_start_attr.attr,
1097 &addr_stop_attr.attr,
1098 &addr_acctype_attr.attr,
1099 &cntr_idx_attr.attr,
1100 &cntr_rld_val_attr.attr,
1101 &cntr_event_attr.attr,
1102 &cntr_rld_event_attr.attr,
1103 &cntr_val_attr.attr,
1104 &seq_12_event_attr.attr,
1105 &seq_21_event_attr.attr,
1106 &seq_23_event_attr.attr,
1107 &seq_31_event_attr.attr,
1108 &seq_32_event_attr.attr,
1109 &seq_13_event_attr.attr,
1110 &seq_curr_state_attr.attr,
1111 &ctxid_idx_attr.attr,
1112 &ctxid_val_attr.attr,
1113 &ctxid_mask_attr.attr,
1114 &sync_freq_attr.attr,
1115 &timestamp_event_attr.attr,
1116 NULL,
1117};
1118
1119static struct attribute_group etm_attr_grp = {
1120 .attrs = etm_attrs,
1121};
1122
Stephen Boyda9510502012-04-24 16:23:34 -07001123static int __devinit etm_sysfs_init(void)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001124{
1125 int ret;
1126
1127 etm.kobj = kobject_create_and_add("etm", qdss_get_modulekobj());
1128 if (!etm.kobj) {
1129 dev_err(etm.dev, "failed to create ETM sysfs kobject\n");
1130 ret = -ENOMEM;
1131 goto err_create;
1132 }
1133
1134 ret = sysfs_create_file(etm.kobj, &enabled_attr.attr);
1135 if (ret) {
1136 dev_err(etm.dev, "failed to create ETM sysfs enabled"
1137 " attribute\n");
1138 goto err_file;
1139 }
1140
1141 if (sysfs_create_group(etm.kobj, &etm_attr_grp))
1142 dev_err(etm.dev, "failed to create ETM sysfs group\n");
1143
1144 return 0;
1145err_file:
1146 kobject_put(etm.kobj);
1147err_create:
1148 return ret;
1149}
1150
Stephen Boyda9510502012-04-24 16:23:34 -07001151static void __devexit etm_sysfs_exit(void)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001152{
1153 sysfs_remove_group(etm.kobj, &etm_attr_grp);
1154 sysfs_remove_file(etm.kobj, &enabled_attr.attr);
1155 kobject_put(etm.kobj);
1156}
1157
Stephen Boyda9510502012-04-24 16:23:34 -07001158static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001159{
Pratik Patel61de7302012-03-07 12:06:10 -08001160 switch (arch) {
1161 case PFT_ARCH_V1_1:
1162 break;
1163 default:
1164 return false;
1165 }
1166 return true;
1167}
1168
Stephen Boyda9510502012-04-24 16:23:34 -07001169static int __devinit etm_arch_init(void)
Pratik Patel61de7302012-03-07 12:06:10 -08001170{
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001171 int ret, i;
Pratik Patel7831c082011-06-08 21:44:37 -07001172 /* use cpu 0 for setup */
1173 int cpu = 0;
Pratik Patel61de7302012-03-07 12:06:10 -08001174 uint32_t etmidr;
1175 uint32_t etmccr;
Pratik Patel7831c082011-06-08 21:44:37 -07001176
Pratik Patel17f3b822011-11-21 12:41:47 -08001177 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel492b3012012-03-06 14:22:30 -08001178 etm_os_unlock(NULL);
1179 smp_call_function(etm_os_unlock, NULL, 1);
1180 ETM_UNLOCK(cpu);
Pratik Patel17f3b822011-11-21 12:41:47 -08001181 /* Vote for ETM power/clock enable */
Pratik Patel61de7302012-03-07 12:06:10 -08001182 etm_clr_pwrdwn(cpu);
1183 /* Set prog bit. It will be set from reset but this is included to
1184 * ensure it is set
1185 */
Pratik Patel492b3012012-03-06 14:22:30 -08001186 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -07001187
1188 /* find all capabilities */
Pratik Patel61de7302012-03-07 12:06:10 -08001189 etmidr = etm_readl(etm, cpu, ETMIDR);
1190 etm.arch = BMVAL(etmidr, 4, 11);
1191 if (etm_arch_supported(etm.arch) == false) {
1192 ret = -EINVAL;
1193 goto err;
1194 }
Pratik Patel7831c082011-06-08 21:44:37 -07001195
Pratik Patel61de7302012-03-07 12:06:10 -08001196 etmccr = etm_readl(etm, cpu, ETMCCR);
1197 etm.nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1198 etm.nr_cntr = BMVAL(etmccr, 13, 15);
1199 etm.nr_ext_inp = BMVAL(etmccr, 17, 19);
1200 etm.nr_ext_out = BMVAL(etmccr, 20, 22);
1201 etm.nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel7831c082011-06-08 21:44:37 -07001202
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001203 if (cpu_is_krait_v1()) {
1204 /* Krait pass1 doesn't support include filtering and non-cycle
1205 * accurate tracing
1206 */
1207 etm.mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1208 etm.ctrl = 0x1000;
1209 etm.enable_ctrl1 = 0x1000000;
1210 for (i = 0; i < etm.nr_addr_cmp; i++) {
1211 etm.addr_val[i] = 0x0;
1212 etm.addr_acctype[i] = 0x0;
1213 etm.addr_type[i] = ETM_ADDR_TYPE_NONE;
1214 }
1215 }
1216
Pratik Patel17f3b822011-11-21 12:41:47 -08001217 /* Vote for ETM power/clock disable */
Pratik Patel61de7302012-03-07 12:06:10 -08001218 etm_set_pwrdwn(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -08001219 ETM_LOCK(cpu);
Pratik Patel61de7302012-03-07 12:06:10 -08001220
1221 return 0;
1222err:
1223 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001224}
1225
Pratik Patel492b3012012-03-06 14:22:30 -08001226static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001227{
Pratik Patele5771792011-09-17 18:33:54 -07001228 int ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001229 struct resource *res;
1230
1231 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1232 if (!res) {
1233 ret = -EINVAL;
1234 goto err_res;
1235 }
1236
Pratik Patel492b3012012-03-06 14:22:30 -08001237 etm.base = ioremap_nocache(res->start, resource_size(res));
1238 if (!etm.base) {
Pratik Patel7831c082011-06-08 21:44:37 -07001239 ret = -EINVAL;
1240 goto err_ioremap;
1241 }
1242
Pratik Patel492b3012012-03-06 14:22:30 -08001243 etm.dev = &pdev->dev;
Pratik Patel7831c082011-06-08 21:44:37 -07001244
Pratik Patel6630ebe2012-03-06 16:44:22 -08001245 mutex_init(&etm.mutex);
Pratik Patel61de7302012-03-07 12:06:10 -08001246 wake_lock_init(&etm.wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
1247 pm_qos_add_request(&etm.qos_req, PM_QOS_CPU_DMA_LATENCY,
1248 PM_QOS_DEFAULT_VALUE);
Pratik Patele10a77c2012-03-20 10:35:16 -07001249 etm.src = qdss_get("msm_etm");
1250 if (IS_ERR(etm.src)) {
1251 ret = PTR_ERR(etm.src);
1252 goto err_qdssget;
1253 }
1254
Pratik Patelcc320a42011-12-22 10:48:14 -08001255 ret = qdss_clk_enable();
Pratik Patel7831c082011-06-08 21:44:37 -07001256 if (ret)
Pratik Patelcc320a42011-12-22 10:48:14 -08001257 goto err_clk;
Pratik Patel7831c082011-06-08 21:44:37 -07001258
Pratik Patel61de7302012-03-07 12:06:10 -08001259 ret = etm_arch_init();
1260 if (ret)
1261 goto err_arch;
Pratik Patel7831c082011-06-08 21:44:37 -07001262
Pratik Patel6630ebe2012-03-06 16:44:22 -08001263 ret = etm_sysfs_init();
1264 if (ret)
1265 goto err_sysfs;
1266
Pratik Patel61de7302012-03-07 12:06:10 -08001267 etm.enabled = false;
Pratik Patel7831c082011-06-08 21:44:37 -07001268
Pratik Patelcc320a42011-12-22 10:48:14 -08001269 qdss_clk_disable();
Pratik Patel7831c082011-06-08 21:44:37 -07001270
Pratik Patel61de7302012-03-07 12:06:10 -08001271 dev_info(etm.dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001272
Pratik Patel61de7302012-03-07 12:06:10 -08001273 if (etm_boot_enable)
1274 etm_enable();
Pratik Patel7831c082011-06-08 21:44:37 -07001275
1276 return 0;
1277
Pratik Patel6630ebe2012-03-06 16:44:22 -08001278err_sysfs:
Pratik Patel61de7302012-03-07 12:06:10 -08001279err_arch:
1280 qdss_clk_disable();
Pratik Patelcc320a42011-12-22 10:48:14 -08001281err_clk:
Pratik Patele10a77c2012-03-20 10:35:16 -07001282 qdss_put(etm.src);
1283err_qdssget:
Pratik Patel61de7302012-03-07 12:06:10 -08001284 pm_qos_remove_request(&etm.qos_req);
1285 wake_lock_destroy(&etm.wake_lock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001286 mutex_destroy(&etm.mutex);
Pratik Patel492b3012012-03-06 14:22:30 -08001287 iounmap(etm.base);
Pratik Patel7831c082011-06-08 21:44:37 -07001288err_ioremap:
1289err_res:
Pratik Patel61de7302012-03-07 12:06:10 -08001290 dev_err(etm.dev, "ETM init failed\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001291 return ret;
1292}
1293
Pratik Patelf6fe9182012-03-20 14:04:18 -07001294static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001295{
Pratik Patel61de7302012-03-07 12:06:10 -08001296 if (etm.enabled)
1297 etm_disable();
Pratik Patel6630ebe2012-03-06 16:44:22 -08001298 etm_sysfs_exit();
Pratik Patele10a77c2012-03-20 10:35:16 -07001299 qdss_put(etm.src);
Pratik Patel492b3012012-03-06 14:22:30 -08001300 pm_qos_remove_request(&etm.qos_req);
1301 wake_lock_destroy(&etm.wake_lock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001302 mutex_destroy(&etm.mutex);
Pratik Patel492b3012012-03-06 14:22:30 -08001303 iounmap(etm.base);
Pratik Patel7831c082011-06-08 21:44:37 -07001304
1305 return 0;
1306}
1307
Pratik Patel492b3012012-03-06 14:22:30 -08001308static struct platform_driver etm_driver = {
1309 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001310 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001311 .driver = {
Pratik Patel492b3012012-03-06 14:22:30 -08001312 .name = "msm_etm",
Pratik Patel7831c082011-06-08 21:44:37 -07001313 },
1314};
1315
Pratik Patel492b3012012-03-06 14:22:30 -08001316int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001317{
Pratik Patel492b3012012-03-06 14:22:30 -08001318 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001319}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001320module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001321
Pratik Patelf6fe9182012-03-20 14:04:18 -07001322void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001323{
Pratik Patel492b3012012-03-06 14:22:30 -08001324 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001325}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001326module_exit(etm_exit);
1327
1328MODULE_LICENSE("GPL v2");
1329MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");