blob: 89653337252b5fd950c83be77ce025f9064630f6 [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>
22#include <linux/miscdevice.h>
23#include <linux/uaccess.h>
24#include <linux/slab.h>
25#include <linux/delay.h>
26#include <linux/smp.h>
Pratik Patel7831c082011-06-08 21:44:37 -070027#include <linux/wakelock.h>
28#include <linux/pm_qos_params.h>
Pratik Patel7831c082011-06-08 21:44:37 -070029#include <asm/atomic.h>
30
31#include "qdss.h"
32
Pratik Patel492b3012012-03-06 14:22:30 -080033#define etm_writel(etm, cpu, val, off) \
34 __raw_writel((val), etm.base + (SZ_4K * cpu) + off)
35#define etm_readl(etm, cpu, off) \
36 __raw_readl(etm.base + (SZ_4K * cpu) + off)
Pratik Patel7831c082011-06-08 21:44:37 -070037
38/*
39 * Device registers:
40 * 0x000 - 0x2FC: Trace registers
41 * 0x300 - 0x314: Management registers
42 * 0x318 - 0xEFC: Trace registers
43 *
44 * Coresight registers
45 * 0xF00 - 0xF9C: Management registers
46 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
47 * Trace registers in PFTv1.1
48 * 0xFA8 - 0xFFC: Management registers
49 */
50
51/* Trace registers (0x000-0x2FC) */
52#define ETMCR (0x000)
53#define ETMCCR (0x004)
54#define ETMTRIGGER (0x008)
55#define ETMSR (0x010)
56#define ETMSCR (0x014)
57#define ETMTSSCR (0x018)
58#define ETMTEEVR (0x020)
59#define ETMTECR1 (0x024)
60#define ETMFFLR (0x02C)
61#define ETMACVRn(n) (0x040 + (n * 4))
62#define ETMACTRn(n) (0x080 + (n * 4))
63#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
64#define ETMCNTENRn(n) (0x150 + (n * 4))
65#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
66#define ETMCNTVRn(n) (0x170 + (n * 4))
67#define ETMSQ12EVR (0x180)
68#define ETMSQ21EVR (0x184)
69#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -080070#define ETMSQ31EVR (0x18C)
71#define ETMSQ32EVR (0x190)
72#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -070073#define ETMSQR (0x19C)
74#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
75#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
76#define ETMCIDCMR (0x1BC)
77#define ETMIMPSPEC0 (0x1C0)
78#define ETMIMPSPEC1 (0x1C4)
79#define ETMIMPSPEC2 (0x1C8)
80#define ETMIMPSPEC3 (0x1CC)
81#define ETMIMPSPEC4 (0x1D0)
82#define ETMIMPSPEC5 (0x1D4)
83#define ETMIMPSPEC6 (0x1D8)
84#define ETMIMPSPEC7 (0x1DC)
85#define ETMSYNCFR (0x1E0)
86#define ETMIDR (0x1E4)
87#define ETMCCER (0x1E8)
88#define ETMEXTINSELR (0x1EC)
89#define ETMTESSEICR (0x1F0)
90#define ETMEIBCR (0x1F4)
91#define ETMTSEVR (0x1F8)
92#define ETMAUXCR (0x1FC)
93#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -080094#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -070095/* Management registers (0x300-0x314) */
96#define ETMOSLAR (0x300)
97#define ETMOSLSR (0x304)
98#define ETMOSSRR (0x308)
99#define ETMPDCR (0x310)
100#define ETMPDSR (0x314)
101
Pratik Patel492b3012012-03-06 14:22:30 -0800102#define ETM_LOCK(cpu) \
Pratik Patel7831c082011-06-08 21:44:37 -0700103do { \
104 mb(); \
Pratik Patel492b3012012-03-06 14:22:30 -0800105 etm_writel(etm, cpu, 0x0, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -0700106} while (0)
Pratik Patel492b3012012-03-06 14:22:30 -0800107#define ETM_UNLOCK(cpu) \
Pratik Patel7831c082011-06-08 21:44:37 -0700108do { \
Pratik Patel492b3012012-03-06 14:22:30 -0800109 etm_writel(etm, cpu, CS_UNLOCK_MAGIC, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -0700110 mb(); \
111} while (0)
112
Pratik Patel7831c082011-06-08 21:44:37 -0700113
114/* Forward declarations */
Pratik Patel492b3012012-03-06 14:22:30 -0800115static void etm_cfg_rw_init(void);
Pratik Patel7831c082011-06-08 21:44:37 -0700116
Pratik Patel29cba152012-01-03 11:40:26 -0800117#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
118static int trace_on_boot = 1;
119#else
Pratik Patel7831c082011-06-08 21:44:37 -0700120static int trace_on_boot;
Pratik Patel29cba152012-01-03 11:40:26 -0800121#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700122module_param_named(
123 trace_on_boot, trace_on_boot, int, S_IRUGO
124);
125
Pratik Patel492b3012012-03-06 14:22:30 -0800126struct etm_config {
Pratik Patel7831c082011-06-08 21:44:37 -0700127 /* read only config registers */
128 uint32_t config_code;
129 /* derived values */
130 uint8_t nr_addr_comp;
131 uint8_t nr_cntr;
132 uint8_t nr_ext_input;
133 uint8_t nr_ext_output;
134 uint8_t nr_context_id_comp;
135
136 uint32_t config_code_extn;
137 /* derived values */
138 uint8_t nr_extnd_ext_input_sel;
139 uint8_t nr_instr_resources;
140
141 uint32_t system_config;
142 /* derived values */
143 uint8_t fifofull_supported;
144 uint8_t nr_procs_supported;
145
146 /* read-write registers */
147 uint32_t main_control;
148 uint32_t trigger_event;
149 uint32_t te_start_stop_control;
150 uint32_t te_event;
151 uint32_t te_control;
152 uint32_t fifofull_level;
153 uint32_t addr_comp_value[16];
154 uint32_t addr_comp_access_type[16];
155 uint32_t cntr_reload_value[4];
156 uint32_t cntr_enable_event[4];
157 uint32_t cntr_reload_event[4];
158 uint32_t cntr_value[4];
159 uint32_t seq_state_12_event;
160 uint32_t seq_state_21_event;
161 uint32_t seq_state_23_event;
162 uint32_t seq_state_32_event;
163 uint32_t seq_state_13_event;
164 uint32_t seq_state_31_event;
165 uint32_t current_seq_state;
166 uint32_t ext_output_event[4];
167 uint32_t context_id_comp_value[3];
168 uint32_t context_id_comp_mask;
169 uint32_t sync_freq;
170 uint32_t extnd_ext_input_sel;
171 uint32_t ts_event;
172 uint32_t aux_control;
173 uint32_t coresight_trace_id;
174 uint32_t vmid_comp_value;
175};
176
Pratik Patel492b3012012-03-06 14:22:30 -0800177struct etm_ctx {
178 struct etm_config cfg;
Pratik Patel7831c082011-06-08 21:44:37 -0700179 void __iomem *base;
Pratik Patel7831c082011-06-08 21:44:37 -0700180 bool trace_enabled;
Pratik Patel7831c082011-06-08 21:44:37 -0700181 struct wake_lock wake_lock;
182 struct pm_qos_request_list qos_req;
183 atomic_t in_use;
184 struct device *dev;
Pratik Patel7831c082011-06-08 21:44:37 -0700185};
186
Pratik Patel492b3012012-03-06 14:22:30 -0800187static struct etm_ctx etm;
Pratik Patel7831c082011-06-08 21:44:37 -0700188
Pratik Patel7831c082011-06-08 21:44:37 -0700189
Pratik Patel17f3b822011-11-21 12:41:47 -0800190/* ETM clock is derived from the processor clock and gets enabled on a
191 * logical OR of below items on Krait (pass2 onwards):
192 * 1.CPMR[ETMCLKEN] is 1
193 * 2.ETMCR[PD] is 0
194 * 3.ETMPDCR[PU] is 1
195 * 4.Reset is asserted (core or debug)
196 * 5.APB memory mapped requests (eg. EDAP access)
197 *
198 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
199 * enables
200 *
201 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
202 * clock vote in the driver and the save-restore code uses 1. above
203 * for its vote
204 */
Pratik Patel492b3012012-03-06 14:22:30 -0800205static void etm_set_powerdown(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700206{
207 uint32_t etmcr;
208
Pratik Patel492b3012012-03-06 14:22:30 -0800209 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700210 etmcr |= BIT(0);
Pratik Patel492b3012012-03-06 14:22:30 -0800211 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700212}
213
Pratik Patel492b3012012-03-06 14:22:30 -0800214static void etm_clear_powerdown(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700215{
216 uint32_t etmcr;
217
Pratik Patel492b3012012-03-06 14:22:30 -0800218 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700219 etmcr &= ~BIT(0);
Pratik Patel492b3012012-03-06 14:22:30 -0800220 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700221}
222
Pratik Patel492b3012012-03-06 14:22:30 -0800223static void etm_set_prog(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700224{
225 uint32_t etmcr;
226 int count;
227
Pratik Patel492b3012012-03-06 14:22:30 -0800228 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700229 etmcr |= BIT(10);
Pratik Patel492b3012012-03-06 14:22:30 -0800230 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700231
Pratik Patel492b3012012-03-06 14:22:30 -0800232 for (count = TIMEOUT_US; BVAL(etm_readl(etm, cpu, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700233 && count > 0; count--)
234 udelay(1);
235 WARN(count == 0, "timeout while setting prog bit\n");
236}
237
Pratik Patel492b3012012-03-06 14:22:30 -0800238static void etm_clear_prog(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700239{
240 uint32_t etmcr;
241 int count;
242
Pratik Patel492b3012012-03-06 14:22:30 -0800243 etmcr = etm_readl(etm, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700244 etmcr &= ~BIT(10);
Pratik Patel492b3012012-03-06 14:22:30 -0800245 etm_writel(etm, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700246
Pratik Patel492b3012012-03-06 14:22:30 -0800247 for (count = TIMEOUT_US; BVAL(etm_readl(etm, cpu, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700248 && count > 0; count--)
249 udelay(1);
250 WARN(count == 0, "timeout while clearing prog bit\n");
251}
252
Pratik Patel492b3012012-03-06 14:22:30 -0800253static void __etm_trace_enable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700254{
Pratik Patel17f3b822011-11-21 12:41:47 -0800255 int i;
Pratik Patel7831c082011-06-08 21:44:37 -0700256
Pratik Patel492b3012012-03-06 14:22:30 -0800257 ETM_UNLOCK(cpu);
Pratik Patel17f3b822011-11-21 12:41:47 -0800258 /* Vote for ETM power/clock enable */
Pratik Patel492b3012012-03-06 14:22:30 -0800259 etm_clear_powerdown(cpu);
260 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700261
Pratik Patel492b3012012-03-06 14:22:30 -0800262 etm_writel(etm, cpu, etm.cfg.main_control | BIT(10), ETMCR);
263 etm_writel(etm, cpu, etm.cfg.trigger_event, ETMTRIGGER);
264 etm_writel(etm, cpu, etm.cfg.te_start_stop_control, ETMTSSCR);
265 etm_writel(etm, cpu, etm.cfg.te_event, ETMTEEVR);
266 etm_writel(etm, cpu, etm.cfg.te_control, ETMTECR1);
267 etm_writel(etm, cpu, etm.cfg.fifofull_level, ETMFFLR);
268 for (i = 0; i < etm.cfg.nr_addr_comp; i++) {
269 etm_writel(etm, cpu, etm.cfg.addr_comp_value[i], ETMACVRn(i));
270 etm_writel(etm, cpu, etm.cfg.addr_comp_access_type[i],
Pratik Patel7831c082011-06-08 21:44:37 -0700271 ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700272 }
Pratik Patel492b3012012-03-06 14:22:30 -0800273 for (i = 0; i < etm.cfg.nr_cntr; i++) {
274 etm_writel(etm, cpu, etm.cfg.cntr_reload_value[i],
Pratik Patel17f3b822011-11-21 12:41:47 -0800275 ETMCNTRLDVRn(i));
Pratik Patel492b3012012-03-06 14:22:30 -0800276 etm_writel(etm, cpu, etm.cfg.cntr_enable_event[i],
Pratik Patel17f3b822011-11-21 12:41:47 -0800277 ETMCNTENRn(i));
Pratik Patel492b3012012-03-06 14:22:30 -0800278 etm_writel(etm, cpu, etm.cfg.cntr_reload_event[i],
Pratik Patel17f3b822011-11-21 12:41:47 -0800279 ETMCNTRLDEVRn(i));
Pratik Patel492b3012012-03-06 14:22:30 -0800280 etm_writel(etm, cpu, etm.cfg.cntr_value[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800281 }
Pratik Patel492b3012012-03-06 14:22:30 -0800282 etm_writel(etm, cpu, etm.cfg.seq_state_12_event, ETMSQ12EVR);
283 etm_writel(etm, cpu, etm.cfg.seq_state_21_event, ETMSQ21EVR);
284 etm_writel(etm, cpu, etm.cfg.seq_state_23_event, ETMSQ23EVR);
285 etm_writel(etm, cpu, etm.cfg.seq_state_32_event, ETMSQ32EVR);
286 etm_writel(etm, cpu, etm.cfg.seq_state_13_event, ETMSQ13EVR);
287 etm_writel(etm, cpu, etm.cfg.seq_state_31_event, ETMSQ31EVR);
288 etm_writel(etm, cpu, etm.cfg.current_seq_state, ETMSQR);
289 for (i = 0; i < etm.cfg.nr_ext_output; i++)
290 etm_writel(etm, cpu, etm.cfg.ext_output_event[i],
Pratik Patel17f3b822011-11-21 12:41:47 -0800291 ETMEXTOUTEVRn(i));
Pratik Patel492b3012012-03-06 14:22:30 -0800292 for (i = 0; i < etm.cfg.nr_context_id_comp; i++)
293 etm_writel(etm, cpu, etm.cfg.context_id_comp_value[i],
Pratik Patel17f3b822011-11-21 12:41:47 -0800294 ETMCIDCVRn(i));
Pratik Patel492b3012012-03-06 14:22:30 -0800295 etm_writel(etm, cpu, etm.cfg.context_id_comp_mask, ETMCIDCMR);
296 etm_writel(etm, cpu, etm.cfg.sync_freq, ETMSYNCFR);
297 etm_writel(etm, cpu, etm.cfg.extnd_ext_input_sel, ETMEXTINSELR);
298 etm_writel(etm, cpu, etm.cfg.ts_event, ETMTSEVR);
299 etm_writel(etm, cpu, etm.cfg.aux_control, ETMAUXCR);
300 etm_writel(etm, cpu, cpu+1, ETMTRACEIDR);
301 etm_writel(etm, cpu, etm.cfg.vmid_comp_value, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800302
Pratik Patel492b3012012-03-06 14:22:30 -0800303 etm_clear_prog(cpu);
304 ETM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700305}
306
Pratik Patel492b3012012-03-06 14:22:30 -0800307static int etm_trace_enable(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700308{
Pratik Patel17f3b822011-11-21 12:41:47 -0800309 int ret, cpu;
Pratik Patel7831c082011-06-08 21:44:37 -0700310
Pratik Patelcc320a42011-12-22 10:48:14 -0800311 ret = qdss_clk_enable();
Pratik Patel7831c082011-06-08 21:44:37 -0700312 if (ret)
313 return ret;
314
Pratik Patel492b3012012-03-06 14:22:30 -0800315 wake_lock(&etm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700316 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700317 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700318 *
319 * we rely on the user to prevent hotplug on/off racing with this
320 * operation and to ensure cores where trace is expected to be turned
321 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700322 */
Pratik Patel492b3012012-03-06 14:22:30 -0800323 pm_qos_update_request(&etm.qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700324
325 etb_disable();
326 tpiu_disable();
327 /* enable ETB first to avoid loosing any trace data */
328 etb_enable();
329 funnel_enable(0x0, 0x3);
Pratik Patel17f3b822011-11-21 12:41:47 -0800330 for_each_online_cpu(cpu)
Pratik Patel492b3012012-03-06 14:22:30 -0800331 __etm_trace_enable(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700332
Pratik Patel492b3012012-03-06 14:22:30 -0800333 etm.trace_enabled = true;
Pratik Patel7831c082011-06-08 21:44:37 -0700334
Pratik Patel492b3012012-03-06 14:22:30 -0800335 pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
336 wake_unlock(&etm.wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700337
338 return 0;
339}
340
Pratik Patel492b3012012-03-06 14:22:30 -0800341static void __etm_trace_disable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700342{
Pratik Patel492b3012012-03-06 14:22:30 -0800343 ETM_UNLOCK(cpu);
344 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700345
Pratik Patel17f3b822011-11-21 12:41:47 -0800346 /* program trace enable to low by using always false event */
Pratik Patel492b3012012-03-06 14:22:30 -0800347 etm_writel(etm, cpu, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700348
Pratik Patel17f3b822011-11-21 12:41:47 -0800349 /* Vote for ETM power/clock disable */
Pratik Patel492b3012012-03-06 14:22:30 -0800350 etm_set_powerdown(cpu);
351 ETM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700352}
353
Pratik Patel492b3012012-03-06 14:22:30 -0800354static void etm_trace_disable(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700355{
Pratik Patel17f3b822011-11-21 12:41:47 -0800356 int cpu;
357
Pratik Patel492b3012012-03-06 14:22:30 -0800358 wake_lock(&etm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700359 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700360 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700361 *
362 * we rely on the user to prevent hotplug on/off racing with this
363 * operation and to ensure cores where trace is expected to be turned
364 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700365 */
Pratik Patel492b3012012-03-06 14:22:30 -0800366 pm_qos_update_request(&etm.qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700367
Pratik Patel17f3b822011-11-21 12:41:47 -0800368 for_each_online_cpu(cpu)
Pratik Patel492b3012012-03-06 14:22:30 -0800369 __etm_trace_disable(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700370 etb_dump();
371 etb_disable();
372 funnel_disable(0x0, 0x3);
373
Pratik Patel492b3012012-03-06 14:22:30 -0800374 etm.trace_enabled = false;
Pratik Patel7831c082011-06-08 21:44:37 -0700375
Pratik Patel492b3012012-03-06 14:22:30 -0800376 pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
377 wake_unlock(&etm.wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700378
Pratik Patelcc320a42011-12-22 10:48:14 -0800379 qdss_clk_disable();
Pratik Patel7831c082011-06-08 21:44:37 -0700380}
381
Pratik Patel492b3012012-03-06 14:22:30 -0800382static int etm_open(struct inode *inode, struct file *file)
Pratik Patel7831c082011-06-08 21:44:37 -0700383{
Pratik Patel492b3012012-03-06 14:22:30 -0800384 if (atomic_cmpxchg(&etm.in_use, 0, 1))
Pratik Patel7831c082011-06-08 21:44:37 -0700385 return -EBUSY;
386
Pratik Patel492b3012012-03-06 14:22:30 -0800387 dev_dbg(etm.dev, "%s: successfully opened\n", __func__);
Pratik Patel7831c082011-06-08 21:44:37 -0700388 return 0;
389}
390
Pratik Patel492b3012012-03-06 14:22:30 -0800391static void etm_range_filter(char range, uint32_t reg1,
Pratik Patel7831c082011-06-08 21:44:37 -0700392 uint32_t addr1, uint32_t reg2, uint32_t addr2)
393{
Pratik Patel492b3012012-03-06 14:22:30 -0800394 etm.cfg.addr_comp_value[reg1] = addr1;
395 etm.cfg.addr_comp_value[reg2] = addr2;
Pratik Patel7831c082011-06-08 21:44:37 -0700396
Pratik Patel492b3012012-03-06 14:22:30 -0800397 etm.cfg.te_control |= (1 << (reg1/2));
Pratik Patel7831c082011-06-08 21:44:37 -0700398 if (range == 'i')
Pratik Patel492b3012012-03-06 14:22:30 -0800399 etm.cfg.te_control &= ~BIT(24);
Pratik Patel7831c082011-06-08 21:44:37 -0700400 else if (range == 'e')
Pratik Patel492b3012012-03-06 14:22:30 -0800401 etm.cfg.te_control |= BIT(24);
Pratik Patel7831c082011-06-08 21:44:37 -0700402}
403
Pratik Patel492b3012012-03-06 14:22:30 -0800404static void etm_start_stop_filter(char start_stop,
Pratik Patel7831c082011-06-08 21:44:37 -0700405 uint32_t reg, uint32_t addr)
406{
Pratik Patel492b3012012-03-06 14:22:30 -0800407 etm.cfg.addr_comp_value[reg] = addr;
Pratik Patel7831c082011-06-08 21:44:37 -0700408
409 if (start_stop == 's')
Pratik Patel492b3012012-03-06 14:22:30 -0800410 etm.cfg.te_start_stop_control |= (1 << reg);
Pratik Patel7831c082011-06-08 21:44:37 -0700411 else if (start_stop == 't')
Pratik Patel492b3012012-03-06 14:22:30 -0800412 etm.cfg.te_start_stop_control |= (1 << (reg + 16));
Pratik Patel7831c082011-06-08 21:44:37 -0700413
Pratik Patel492b3012012-03-06 14:22:30 -0800414 etm.cfg.te_control |= BIT(25);
Pratik Patel7831c082011-06-08 21:44:37 -0700415}
416
417#define MAX_COMMAND_STRLEN 40
Pratik Patel492b3012012-03-06 14:22:30 -0800418static ssize_t etm_write(struct file *file, const char __user *data,
Pratik Patel7831c082011-06-08 21:44:37 -0700419 size_t len, loff_t *ppos)
420{
421 char command[MAX_COMMAND_STRLEN];
422 int str_len;
423 unsigned long reg1, reg2;
424 unsigned long addr1, addr2;
425
426 str_len = strnlen_user(data, MAX_COMMAND_STRLEN);
Pratik Patel492b3012012-03-06 14:22:30 -0800427 dev_dbg(etm.dev, "string length: %d", str_len);
Pratik Patel7831c082011-06-08 21:44:37 -0700428 if (str_len == 0 || str_len == (MAX_COMMAND_STRLEN+1)) {
Pratik Patel492b3012012-03-06 14:22:30 -0800429 dev_err(etm.dev, "error in str_len: %d", str_len);
Pratik Patel7831c082011-06-08 21:44:37 -0700430 return -EFAULT;
431 }
432 /* includes the null character */
433 if (copy_from_user(command, data, str_len)) {
Pratik Patel492b3012012-03-06 14:22:30 -0800434 dev_err(etm.dev, "error in copy_from_user: %d", str_len);
Pratik Patel7831c082011-06-08 21:44:37 -0700435 return -EFAULT;
436 }
437
Pratik Patel492b3012012-03-06 14:22:30 -0800438 dev_dbg(etm.dev, "input = %s", command);
Pratik Patel7831c082011-06-08 21:44:37 -0700439
440 switch (command[0]) {
441 case '0':
Pratik Patel492b3012012-03-06 14:22:30 -0800442 if (etm.trace_enabled) {
443 etm_trace_disable();
444 dev_info(etm.dev, "tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700445 } else
Pratik Patel492b3012012-03-06 14:22:30 -0800446 dev_err(etm.dev, "trace already disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700447
448 break;
449 case '1':
Pratik Patel492b3012012-03-06 14:22:30 -0800450 if (!etm.trace_enabled) {
451 if (!etm_trace_enable())
452 dev_info(etm.dev, "tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700453 else
Pratik Patel492b3012012-03-06 14:22:30 -0800454 dev_err(etm.dev, "error enabling trace\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700455 } else
Pratik Patel492b3012012-03-06 14:22:30 -0800456 dev_err(etm.dev, "trace already enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700457 break;
458 case 'f':
459 switch (command[2]) {
460 case 'i':
461 switch (command[4]) {
462 case 'i':
463 if (sscanf(&command[6], "%lx:%lx:%lx:%lx\\0",
464 &reg1, &addr1, &reg2, &addr2) != 4)
465 goto err_out;
466 if (reg1 > 7 || reg2 > 7 || (reg1 % 2))
467 goto err_out;
Pratik Patel492b3012012-03-06 14:22:30 -0800468 etm_range_filter('i',
Pratik Patel7831c082011-06-08 21:44:37 -0700469 reg1, addr1, reg2, addr2);
470 break;
471 case 'e':
472 if (sscanf(&command[6], "%lx:%lx:%lx:%lx\\0",
473 &reg1, &addr1, &reg2, &addr2) != 4)
474 goto err_out;
475 if (reg1 > 7 || reg2 > 7 || (reg1 % 2)
476 || command[2] == 'd')
477 goto err_out;
Pratik Patel492b3012012-03-06 14:22:30 -0800478 etm_range_filter('e',
Pratik Patel7831c082011-06-08 21:44:37 -0700479 reg1, addr1, reg2, addr2);
480 break;
481 case 's':
482 if (sscanf(&command[6], "%lx:%lx\\0",
483 &reg1, &addr1) != 2)
484 goto err_out;
485 if (reg1 > 7)
486 goto err_out;
Pratik Patel492b3012012-03-06 14:22:30 -0800487 etm_start_stop_filter('s', reg1, addr1);
Pratik Patel7831c082011-06-08 21:44:37 -0700488 break;
489 case 't':
490 if (sscanf(&command[6], "%lx:%lx\\0",
491 &reg1, &addr1) != 2)
492 goto err_out;
493 if (reg1 > 7)
494 goto err_out;
Pratik Patel492b3012012-03-06 14:22:30 -0800495 etm_start_stop_filter('t', reg1, addr1);
Pratik Patel7831c082011-06-08 21:44:37 -0700496 break;
497 default:
498 goto err_out;
499 }
500 break;
501 case 'r':
Pratik Patel492b3012012-03-06 14:22:30 -0800502 etm_cfg_rw_init();
Pratik Patel7831c082011-06-08 21:44:37 -0700503 break;
504 default:
505 goto err_out;
506 }
507 break;
508 default:
509 goto err_out;
510 }
511
512 return len;
513
514err_out:
515 return -EFAULT;
516}
517
Pratik Patel492b3012012-03-06 14:22:30 -0800518static int etm_release(struct inode *inode, struct file *file)
Pratik Patel7831c082011-06-08 21:44:37 -0700519{
Pratik Patel492b3012012-03-06 14:22:30 -0800520 atomic_set(&etm.in_use, 0);
521 dev_dbg(etm.dev, "%s: released\n", __func__);
Pratik Patel7831c082011-06-08 21:44:37 -0700522 return 0;
523}
524
Pratik Patel492b3012012-03-06 14:22:30 -0800525static const struct file_operations etm_fops = {
Pratik Patel7831c082011-06-08 21:44:37 -0700526 .owner = THIS_MODULE,
Pratik Patel492b3012012-03-06 14:22:30 -0800527 .open = etm_open,
528 .write = etm_write,
529 .release = etm_release,
Pratik Patel7831c082011-06-08 21:44:37 -0700530};
531
Pratik Patel492b3012012-03-06 14:22:30 -0800532static struct miscdevice etm_misc = {
533 .name = "msm_etm",
Pratik Patel7831c082011-06-08 21:44:37 -0700534 .minor = MISC_DYNAMIC_MINOR,
Pratik Patel492b3012012-03-06 14:22:30 -0800535 .fops = &etm_fops,
Pratik Patel7831c082011-06-08 21:44:37 -0700536};
537
Pratik Patel492b3012012-03-06 14:22:30 -0800538static void etm_cfg_rw_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700539{
540 int i;
541
Pratik Patel492b3012012-03-06 14:22:30 -0800542 etm.cfg.main_control = 0x00001000;
543 etm.cfg.trigger_event = 0x0000406F;
544 etm.cfg.te_start_stop_control = 0x00000000;
545 etm.cfg.te_event = 0x0000006F;
546 etm.cfg.te_control = 0x01000000;
547 etm.cfg.fifofull_level = 0x00000028;
548 for (i = 0; i < etm.cfg.nr_addr_comp; i++) {
549 etm.cfg.addr_comp_value[i] = 0x00000000;
550 etm.cfg.addr_comp_access_type[i] = 0x00000000;
Pratik Patel7831c082011-06-08 21:44:37 -0700551 }
Pratik Patel492b3012012-03-06 14:22:30 -0800552 for (i = 0; i < etm.cfg.nr_cntr; i++) {
553 etm.cfg.cntr_reload_value[i] = 0x00000000;
554 etm.cfg.cntr_enable_event[i] = 0x0000406F;
555 etm.cfg.cntr_reload_event[i] = 0x0000406F;
556 etm.cfg.cntr_value[i] = 0x00000000;
Pratik Patel7831c082011-06-08 21:44:37 -0700557 }
Pratik Patel492b3012012-03-06 14:22:30 -0800558 etm.cfg.seq_state_12_event = 0x0000406F;
559 etm.cfg.seq_state_21_event = 0x0000406F;
560 etm.cfg.seq_state_23_event = 0x0000406F;
561 etm.cfg.seq_state_32_event = 0x0000406F;
562 etm.cfg.seq_state_13_event = 0x0000406F;
563 etm.cfg.seq_state_31_event = 0x0000406F;
564 etm.cfg.current_seq_state = 0x00000000;
565 for (i = 0; i < etm.cfg.nr_ext_output; i++)
566 etm.cfg.ext_output_event[i] = 0x0000406F;
567 for (i = 0; i < etm.cfg.nr_context_id_comp; i++)
568 etm.cfg.context_id_comp_value[i] = 0x00000000;
569 etm.cfg.context_id_comp_mask = 0x00000000;
570 etm.cfg.sync_freq = 0x00000080;
571 etm.cfg.extnd_ext_input_sel = 0x00000000;
572 etm.cfg.ts_event = 0x0000406F;
573 etm.cfg.aux_control = 0x00000000;
574 etm.cfg.vmid_comp_value = 0x00000000;
Pratik Patel7831c082011-06-08 21:44:37 -0700575}
576
Pratik Patel17f3b822011-11-21 12:41:47 -0800577/* Memory mapped writes to clear os lock not supported */
Pratik Patel492b3012012-03-06 14:22:30 -0800578static void etm_os_unlock(void *unused)
Pratik Patel17f3b822011-11-21 12:41:47 -0800579{
580 unsigned long value = 0x0;
581
582 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
583 asm("isb\n\t");
584}
585
Pratik Patel492b3012012-03-06 14:22:30 -0800586static void etm_cfg_ro_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700587{
588 /* use cpu 0 for setup */
589 int cpu = 0;
590
Pratik Patel17f3b822011-11-21 12:41:47 -0800591 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel492b3012012-03-06 14:22:30 -0800592 etm_os_unlock(NULL);
593 smp_call_function(etm_os_unlock, NULL, 1);
594 ETM_UNLOCK(cpu);
Pratik Patel17f3b822011-11-21 12:41:47 -0800595 /* Vote for ETM power/clock enable */
Pratik Patel492b3012012-03-06 14:22:30 -0800596 etm_clear_powerdown(cpu);
597 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700598
599 /* find all capabilities */
Pratik Patel492b3012012-03-06 14:22:30 -0800600 etm.cfg.config_code = etm_readl(etm, cpu, ETMCCR);
601 etm.cfg.nr_addr_comp = BMVAL(etm.cfg.config_code, 0, 3) * 2;
602 etm.cfg.nr_cntr = BMVAL(etm.cfg.config_code, 13, 15);
603 etm.cfg.nr_ext_input = BMVAL(etm.cfg.config_code, 17, 19);
604 etm.cfg.nr_ext_output = BMVAL(etm.cfg.config_code, 20, 22);
605 etm.cfg.nr_context_id_comp = BMVAL(etm.cfg.config_code, 24, 25);
Pratik Patel7831c082011-06-08 21:44:37 -0700606
Pratik Patel492b3012012-03-06 14:22:30 -0800607 etm.cfg.config_code_extn = etm_readl(etm, cpu, ETMCCER);
608 etm.cfg.nr_extnd_ext_input_sel =
609 BMVAL(etm.cfg.config_code_extn, 0, 2);
610 etm.cfg.nr_instr_resources = BMVAL(etm.cfg.config_code_extn, 13, 15);
Pratik Patel7831c082011-06-08 21:44:37 -0700611
Pratik Patel492b3012012-03-06 14:22:30 -0800612 etm.cfg.system_config = etm_readl(etm, cpu, ETMSCR);
613 etm.cfg.fifofull_supported = BVAL(etm.cfg.system_config, 8);
614 etm.cfg.nr_procs_supported = BMVAL(etm.cfg.system_config, 12, 14);
Pratik Patel7831c082011-06-08 21:44:37 -0700615
Pratik Patel17f3b822011-11-21 12:41:47 -0800616 /* Vote for ETM power/clock disable */
Pratik Patel492b3012012-03-06 14:22:30 -0800617 etm_set_powerdown(cpu);
618 ETM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700619}
620
Pratik Patel492b3012012-03-06 14:22:30 -0800621static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700622{
Pratik Patele5771792011-09-17 18:33:54 -0700623 int ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700624 struct resource *res;
625
626 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
627 if (!res) {
628 ret = -EINVAL;
629 goto err_res;
630 }
631
Pratik Patel492b3012012-03-06 14:22:30 -0800632 etm.base = ioremap_nocache(res->start, resource_size(res));
633 if (!etm.base) {
Pratik Patel7831c082011-06-08 21:44:37 -0700634 ret = -EINVAL;
635 goto err_ioremap;
636 }
637
Pratik Patel492b3012012-03-06 14:22:30 -0800638 etm.dev = &pdev->dev;
Pratik Patel7831c082011-06-08 21:44:37 -0700639
Pratik Patel492b3012012-03-06 14:22:30 -0800640 ret = misc_register(&etm_misc);
Pratik Patel7831c082011-06-08 21:44:37 -0700641 if (ret)
642 goto err_misc;
643
Pratik Patelcc320a42011-12-22 10:48:14 -0800644 ret = qdss_clk_enable();
Pratik Patel7831c082011-06-08 21:44:37 -0700645 if (ret)
Pratik Patelcc320a42011-12-22 10:48:14 -0800646 goto err_clk;
Pratik Patel7831c082011-06-08 21:44:37 -0700647
Pratik Patel492b3012012-03-06 14:22:30 -0800648 etm_cfg_ro_init();
649 etm_cfg_rw_init();
Pratik Patel7831c082011-06-08 21:44:37 -0700650
Pratik Patel492b3012012-03-06 14:22:30 -0800651 etm.trace_enabled = false;
Pratik Patel7831c082011-06-08 21:44:37 -0700652
Pratik Patel492b3012012-03-06 14:22:30 -0800653 wake_lock_init(&etm.wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
654 pm_qos_add_request(&etm.qos_req, PM_QOS_CPU_DMA_LATENCY,
Pratik Patel7831c082011-06-08 21:44:37 -0700655 PM_QOS_DEFAULT_VALUE);
Pratik Patel492b3012012-03-06 14:22:30 -0800656 atomic_set(&etm.in_use, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700657
Pratik Patelcc320a42011-12-22 10:48:14 -0800658 qdss_clk_disable();
Pratik Patel7831c082011-06-08 21:44:37 -0700659
Pratik Patel492b3012012-03-06 14:22:30 -0800660 dev_info(etm.dev, "ETM intialized.\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700661
662 if (trace_on_boot) {
Pratik Patel492b3012012-03-06 14:22:30 -0800663 if (!etm_trace_enable())
664 dev_info(etm.dev, "tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700665 else
Pratik Patel492b3012012-03-06 14:22:30 -0800666 dev_err(etm.dev, "error enabling trace\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700667 }
668
669 return 0;
670
Pratik Patelcc320a42011-12-22 10:48:14 -0800671err_clk:
Pratik Patel492b3012012-03-06 14:22:30 -0800672 misc_deregister(&etm_misc);
Pratik Patel7831c082011-06-08 21:44:37 -0700673err_misc:
Pratik Patel492b3012012-03-06 14:22:30 -0800674 iounmap(etm.base);
Pratik Patel7831c082011-06-08 21:44:37 -0700675err_ioremap:
676err_res:
677 return ret;
678}
679
Pratik Patel492b3012012-03-06 14:22:30 -0800680static int etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700681{
Pratik Patel492b3012012-03-06 14:22:30 -0800682 if (etm.trace_enabled)
683 etm_trace_disable();
684 pm_qos_remove_request(&etm.qos_req);
685 wake_lock_destroy(&etm.wake_lock);
686 misc_deregister(&etm_misc);
687 iounmap(etm.base);
Pratik Patel7831c082011-06-08 21:44:37 -0700688
689 return 0;
690}
691
Pratik Patel492b3012012-03-06 14:22:30 -0800692static struct platform_driver etm_driver = {
693 .probe = etm_probe,
694 .remove = etm_remove,
Pratik Patel7831c082011-06-08 21:44:37 -0700695 .driver = {
Pratik Patel492b3012012-03-06 14:22:30 -0800696 .name = "msm_etm",
Pratik Patel7831c082011-06-08 21:44:37 -0700697 },
698};
699
Pratik Patel492b3012012-03-06 14:22:30 -0800700int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700701{
Pratik Patel492b3012012-03-06 14:22:30 -0800702 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -0700703}
Pratik Patel7831c082011-06-08 21:44:37 -0700704
Pratik Patel492b3012012-03-06 14:22:30 -0800705void etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700706{
Pratik Patel492b3012012-03-06 14:22:30 -0800707 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -0700708}