blob: d0d841a07cbc1110dbc6ad3107736ab702078698 [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
33#define ptm_writel(ptm, cpu, val, off) \
34 __raw_writel((val), ptm.base + (SZ_4K * cpu) + off)
35#define ptm_readl(ptm, cpu, off) \
36 __raw_readl(ptm.base + (SZ_4K * cpu) + off)
37
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)
70#define ETMSQ32EVR (0x18C)
71#define ETMSQ13EVR (0x190)
72#define ETMSQ31EVR (0x194)
73#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)
94#define ETMVMIDCVR (0x204)
95/* 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 Patel7831c082011-06-08 21:44:37 -0700102#define PTM_LOCK(cpu) \
103do { \
104 mb(); \
Pratik Patel17f3b822011-11-21 12:41:47 -0800105 ptm_writel(ptm, cpu, 0x0, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -0700106} while (0)
107#define PTM_UNLOCK(cpu) \
108do { \
Pratik Patel17f3b822011-11-21 12:41:47 -0800109 ptm_writel(ptm, 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 */
115static void ptm_cfg_rw_init(void);
116
117static int trace_on_boot;
118module_param_named(
119 trace_on_boot, trace_on_boot, int, S_IRUGO
120);
121
122struct ptm_config {
123 /* read only config registers */
124 uint32_t config_code;
125 /* derived values */
126 uint8_t nr_addr_comp;
127 uint8_t nr_cntr;
128 uint8_t nr_ext_input;
129 uint8_t nr_ext_output;
130 uint8_t nr_context_id_comp;
131
132 uint32_t config_code_extn;
133 /* derived values */
134 uint8_t nr_extnd_ext_input_sel;
135 uint8_t nr_instr_resources;
136
137 uint32_t system_config;
138 /* derived values */
139 uint8_t fifofull_supported;
140 uint8_t nr_procs_supported;
141
142 /* read-write registers */
143 uint32_t main_control;
144 uint32_t trigger_event;
145 uint32_t te_start_stop_control;
146 uint32_t te_event;
147 uint32_t te_control;
148 uint32_t fifofull_level;
149 uint32_t addr_comp_value[16];
150 uint32_t addr_comp_access_type[16];
151 uint32_t cntr_reload_value[4];
152 uint32_t cntr_enable_event[4];
153 uint32_t cntr_reload_event[4];
154 uint32_t cntr_value[4];
155 uint32_t seq_state_12_event;
156 uint32_t seq_state_21_event;
157 uint32_t seq_state_23_event;
158 uint32_t seq_state_32_event;
159 uint32_t seq_state_13_event;
160 uint32_t seq_state_31_event;
161 uint32_t current_seq_state;
162 uint32_t ext_output_event[4];
163 uint32_t context_id_comp_value[3];
164 uint32_t context_id_comp_mask;
165 uint32_t sync_freq;
166 uint32_t extnd_ext_input_sel;
167 uint32_t ts_event;
168 uint32_t aux_control;
169 uint32_t coresight_trace_id;
170 uint32_t vmid_comp_value;
171};
172
173struct ptm_ctx {
174 struct ptm_config cfg;
175 void __iomem *base;
Pratik Patel7831c082011-06-08 21:44:37 -0700176 bool trace_enabled;
Pratik Patel7831c082011-06-08 21:44:37 -0700177 struct wake_lock wake_lock;
178 struct pm_qos_request_list qos_req;
179 atomic_t in_use;
180 struct device *dev;
Pratik Patel7831c082011-06-08 21:44:37 -0700181};
182
183static struct ptm_ctx ptm;
184
Pratik Patel7831c082011-06-08 21:44:37 -0700185
Pratik Patel17f3b822011-11-21 12:41:47 -0800186/* ETM clock is derived from the processor clock and gets enabled on a
187 * logical OR of below items on Krait (pass2 onwards):
188 * 1.CPMR[ETMCLKEN] is 1
189 * 2.ETMCR[PD] is 0
190 * 3.ETMPDCR[PU] is 1
191 * 4.Reset is asserted (core or debug)
192 * 5.APB memory mapped requests (eg. EDAP access)
193 *
194 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
195 * enables
196 *
197 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
198 * clock vote in the driver and the save-restore code uses 1. above
199 * for its vote
200 */
Pratik Patel7831c082011-06-08 21:44:37 -0700201static void ptm_set_powerdown(int cpu)
202{
203 uint32_t etmcr;
204
205 etmcr = ptm_readl(ptm, cpu, ETMCR);
206 etmcr |= BIT(0);
207 ptm_writel(ptm, cpu, etmcr, ETMCR);
208}
209
210static void ptm_clear_powerdown(int cpu)
211{
212 uint32_t etmcr;
213
214 etmcr = ptm_readl(ptm, cpu, ETMCR);
215 etmcr &= ~BIT(0);
216 ptm_writel(ptm, cpu, etmcr, ETMCR);
217}
218
219static void ptm_set_prog(int cpu)
220{
221 uint32_t etmcr;
222 int count;
223
224 etmcr = ptm_readl(ptm, cpu, ETMCR);
225 etmcr |= BIT(10);
226 ptm_writel(ptm, cpu, etmcr, ETMCR);
227
228 for (count = TIMEOUT_US; BVAL(ptm_readl(ptm, cpu, ETMSR), 1) != 1
229 && count > 0; count--)
230 udelay(1);
231 WARN(count == 0, "timeout while setting prog bit\n");
232}
233
234static void ptm_clear_prog(int cpu)
235{
236 uint32_t etmcr;
237 int count;
238
239 etmcr = ptm_readl(ptm, cpu, ETMCR);
240 etmcr &= ~BIT(10);
241 ptm_writel(ptm, cpu, etmcr, ETMCR);
242
243 for (count = TIMEOUT_US; BVAL(ptm_readl(ptm, cpu, ETMSR), 1) != 0
244 && count > 0; count--)
245 udelay(1);
246 WARN(count == 0, "timeout while clearing prog bit\n");
247}
248
Pratik Patel17f3b822011-11-21 12:41:47 -0800249static void __ptm_trace_enable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700250{
Pratik Patel17f3b822011-11-21 12:41:47 -0800251 int i;
Pratik Patel7831c082011-06-08 21:44:37 -0700252
Pratik Patel17f3b822011-11-21 12:41:47 -0800253 PTM_UNLOCK(cpu);
254 /* Vote for ETM power/clock enable */
255 ptm_clear_powerdown(cpu);
256 ptm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700257
Pratik Patel17f3b822011-11-21 12:41:47 -0800258 ptm_writel(ptm, cpu, ptm.cfg.main_control | BIT(10), ETMCR);
259 ptm_writel(ptm, cpu, ptm.cfg.trigger_event, ETMTRIGGER);
260 ptm_writel(ptm, cpu, ptm.cfg.te_start_stop_control, ETMTSSCR);
261 ptm_writel(ptm, cpu, ptm.cfg.te_event, ETMTEEVR);
262 ptm_writel(ptm, cpu, ptm.cfg.te_control, ETMTECR1);
263 ptm_writel(ptm, cpu, ptm.cfg.fifofull_level, ETMFFLR);
264 for (i = 0; i < ptm.cfg.nr_addr_comp; i++) {
265 ptm_writel(ptm, cpu, ptm.cfg.addr_comp_value[i], ETMACVRn(i));
266 ptm_writel(ptm, cpu, ptm.cfg.addr_comp_access_type[i],
Pratik Patel7831c082011-06-08 21:44:37 -0700267 ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700268 }
Pratik Patel17f3b822011-11-21 12:41:47 -0800269 for (i = 0; i < ptm.cfg.nr_cntr; i++) {
270 ptm_writel(ptm, cpu, ptm.cfg.cntr_reload_value[i],
271 ETMCNTRLDVRn(i));
272 ptm_writel(ptm, cpu, ptm.cfg.cntr_enable_event[i],
273 ETMCNTENRn(i));
274 ptm_writel(ptm, cpu, ptm.cfg.cntr_reload_event[i],
275 ETMCNTRLDEVRn(i));
276 ptm_writel(ptm, cpu, ptm.cfg.cntr_value[i], ETMCNTVRn(i));
277 }
278 ptm_writel(ptm, cpu, ptm.cfg.seq_state_12_event, ETMSQ12EVR);
279 ptm_writel(ptm, cpu, ptm.cfg.seq_state_21_event, ETMSQ21EVR);
280 ptm_writel(ptm, cpu, ptm.cfg.seq_state_23_event, ETMSQ23EVR);
281 ptm_writel(ptm, cpu, ptm.cfg.seq_state_32_event, ETMSQ32EVR);
282 ptm_writel(ptm, cpu, ptm.cfg.seq_state_13_event, ETMSQ13EVR);
283 ptm_writel(ptm, cpu, ptm.cfg.seq_state_31_event, ETMSQ31EVR);
284 ptm_writel(ptm, cpu, ptm.cfg.current_seq_state, ETMSQR);
285 for (i = 0; i < ptm.cfg.nr_ext_output; i++)
286 ptm_writel(ptm, cpu, ptm.cfg.ext_output_event[i],
287 ETMEXTOUTEVRn(i));
288 for (i = 0; i < ptm.cfg.nr_context_id_comp; i++)
289 ptm_writel(ptm, cpu, ptm.cfg.context_id_comp_value[i],
290 ETMCIDCVRn(i));
291 ptm_writel(ptm, cpu, ptm.cfg.context_id_comp_mask, ETMCIDCMR);
292 ptm_writel(ptm, cpu, ptm.cfg.sync_freq, ETMSYNCFR);
293 ptm_writel(ptm, cpu, ptm.cfg.extnd_ext_input_sel, ETMEXTINSELR);
294 ptm_writel(ptm, cpu, ptm.cfg.ts_event, ETMTSEVR);
295 ptm_writel(ptm, cpu, ptm.cfg.aux_control, ETMAUXCR);
296 ptm_writel(ptm, cpu, cpu+1, ETMTRACEIDR);
297 ptm_writel(ptm, cpu, ptm.cfg.vmid_comp_value, ETMVMIDCVR);
298
299 ptm_clear_prog(cpu);
300 PTM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700301}
302
303static int ptm_trace_enable(void)
304{
Pratik Patel17f3b822011-11-21 12:41:47 -0800305 int ret, cpu;
Pratik Patel7831c082011-06-08 21:44:37 -0700306
Pratik Patelcc320a42011-12-22 10:48:14 -0800307 ret = qdss_clk_enable();
Pratik Patel7831c082011-06-08 21:44:37 -0700308 if (ret)
309 return ret;
310
311 wake_lock(&ptm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700312 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700313 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700314 *
315 * we rely on the user to prevent hotplug on/off racing with this
316 * operation and to ensure cores where trace is expected to be turned
317 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700318 */
319 pm_qos_update_request(&ptm.qos_req, 0);
320
321 etb_disable();
322 tpiu_disable();
323 /* enable ETB first to avoid loosing any trace data */
324 etb_enable();
325 funnel_enable(0x0, 0x3);
Pratik Patel17f3b822011-11-21 12:41:47 -0800326 for_each_online_cpu(cpu)
327 __ptm_trace_enable(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700328
329 ptm.trace_enabled = true;
330
331 pm_qos_update_request(&ptm.qos_req, PM_QOS_DEFAULT_VALUE);
332 wake_unlock(&ptm.wake_lock);
333
334 return 0;
335}
336
Pratik Patel17f3b822011-11-21 12:41:47 -0800337static void __ptm_trace_disable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700338{
Pratik Patel17f3b822011-11-21 12:41:47 -0800339 PTM_UNLOCK(cpu);
340 ptm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700341
Pratik Patel17f3b822011-11-21 12:41:47 -0800342 /* program trace enable to low by using always false event */
343 ptm_writel(ptm, cpu, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700344
Pratik Patel17f3b822011-11-21 12:41:47 -0800345 /* Vote for ETM power/clock disable */
346 ptm_set_powerdown(cpu);
347 PTM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700348}
349
350static void ptm_trace_disable(void)
351{
Pratik Patel17f3b822011-11-21 12:41:47 -0800352 int cpu;
353
Pratik Patel7831c082011-06-08 21:44:37 -0700354 wake_lock(&ptm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700355 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700356 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700357 *
358 * we rely on the user to prevent hotplug on/off racing with this
359 * operation and to ensure cores where trace is expected to be turned
360 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700361 */
362 pm_qos_update_request(&ptm.qos_req, 0);
363
Pratik Patel17f3b822011-11-21 12:41:47 -0800364 for_each_online_cpu(cpu)
365 __ptm_trace_disable(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700366 etb_dump();
367 etb_disable();
368 funnel_disable(0x0, 0x3);
369
370 ptm.trace_enabled = false;
371
Pratik Patel7831c082011-06-08 21:44:37 -0700372 pm_qos_update_request(&ptm.qos_req, PM_QOS_DEFAULT_VALUE);
373 wake_unlock(&ptm.wake_lock);
374
Pratik Patelcc320a42011-12-22 10:48:14 -0800375 qdss_clk_disable();
Pratik Patel7831c082011-06-08 21:44:37 -0700376}
377
378static int ptm_open(struct inode *inode, struct file *file)
379{
380 if (atomic_cmpxchg(&ptm.in_use, 0, 1))
381 return -EBUSY;
382
383 dev_dbg(ptm.dev, "%s: successfully opened\n", __func__);
384 return 0;
385}
386
387static void ptm_range_filter(char range, uint32_t reg1,
388 uint32_t addr1, uint32_t reg2, uint32_t addr2)
389{
390 ptm.cfg.addr_comp_value[reg1] = addr1;
391 ptm.cfg.addr_comp_value[reg2] = addr2;
392
393 ptm.cfg.te_control |= (1 << (reg1/2));
394 if (range == 'i')
395 ptm.cfg.te_control &= ~BIT(24);
396 else if (range == 'e')
397 ptm.cfg.te_control |= BIT(24);
398}
399
400static void ptm_start_stop_filter(char start_stop,
401 uint32_t reg, uint32_t addr)
402{
403 ptm.cfg.addr_comp_value[reg] = addr;
404
405 if (start_stop == 's')
406 ptm.cfg.te_start_stop_control |= (1 << reg);
407 else if (start_stop == 't')
408 ptm.cfg.te_start_stop_control |= (1 << (reg + 16));
409
410 ptm.cfg.te_control |= BIT(25);
411}
412
413#define MAX_COMMAND_STRLEN 40
414static ssize_t ptm_write(struct file *file, const char __user *data,
415 size_t len, loff_t *ppos)
416{
417 char command[MAX_COMMAND_STRLEN];
418 int str_len;
419 unsigned long reg1, reg2;
420 unsigned long addr1, addr2;
421
422 str_len = strnlen_user(data, MAX_COMMAND_STRLEN);
423 dev_dbg(ptm.dev, "string length: %d", str_len);
424 if (str_len == 0 || str_len == (MAX_COMMAND_STRLEN+1)) {
425 dev_err(ptm.dev, "error in str_len: %d", str_len);
426 return -EFAULT;
427 }
428 /* includes the null character */
429 if (copy_from_user(command, data, str_len)) {
430 dev_err(ptm.dev, "error in copy_from_user: %d", str_len);
431 return -EFAULT;
432 }
433
434 dev_dbg(ptm.dev, "input = %s", command);
435
436 switch (command[0]) {
437 case '0':
438 if (ptm.trace_enabled) {
439 ptm_trace_disable();
440 dev_info(ptm.dev, "tracing disabled\n");
441 } else
442 dev_err(ptm.dev, "trace already disabled\n");
443
444 break;
445 case '1':
446 if (!ptm.trace_enabled) {
447 if (!ptm_trace_enable())
448 dev_info(ptm.dev, "tracing enabled\n");
449 else
450 dev_err(ptm.dev, "error enabling trace\n");
451 } else
452 dev_err(ptm.dev, "trace already enabled\n");
453 break;
454 case 'f':
455 switch (command[2]) {
456 case 'i':
457 switch (command[4]) {
458 case 'i':
459 if (sscanf(&command[6], "%lx:%lx:%lx:%lx\\0",
460 &reg1, &addr1, &reg2, &addr2) != 4)
461 goto err_out;
462 if (reg1 > 7 || reg2 > 7 || (reg1 % 2))
463 goto err_out;
464 ptm_range_filter('i',
465 reg1, addr1, reg2, addr2);
466 break;
467 case 'e':
468 if (sscanf(&command[6], "%lx:%lx:%lx:%lx\\0",
469 &reg1, &addr1, &reg2, &addr2) != 4)
470 goto err_out;
471 if (reg1 > 7 || reg2 > 7 || (reg1 % 2)
472 || command[2] == 'd')
473 goto err_out;
474 ptm_range_filter('e',
475 reg1, addr1, reg2, addr2);
476 break;
477 case 's':
478 if (sscanf(&command[6], "%lx:%lx\\0",
479 &reg1, &addr1) != 2)
480 goto err_out;
481 if (reg1 > 7)
482 goto err_out;
483 ptm_start_stop_filter('s', reg1, addr1);
484 break;
485 case 't':
486 if (sscanf(&command[6], "%lx:%lx\\0",
487 &reg1, &addr1) != 2)
488 goto err_out;
489 if (reg1 > 7)
490 goto err_out;
491 ptm_start_stop_filter('t', reg1, addr1);
492 break;
493 default:
494 goto err_out;
495 }
496 break;
497 case 'r':
498 ptm_cfg_rw_init();
499 break;
500 default:
501 goto err_out;
502 }
503 break;
504 default:
505 goto err_out;
506 }
507
508 return len;
509
510err_out:
511 return -EFAULT;
512}
513
514static int ptm_release(struct inode *inode, struct file *file)
515{
516 atomic_set(&ptm.in_use, 0);
517 dev_dbg(ptm.dev, "%s: released\n", __func__);
518 return 0;
519}
520
521static const struct file_operations ptm_fops = {
522 .owner = THIS_MODULE,
523 .open = ptm_open,
524 .write = ptm_write,
525 .release = ptm_release,
526};
527
528static struct miscdevice ptm_misc = {
529 .name = "msm_ptm",
530 .minor = MISC_DYNAMIC_MINOR,
531 .fops = &ptm_fops,
532};
533
Pratik Patel7831c082011-06-08 21:44:37 -0700534static void ptm_cfg_rw_init(void)
535{
536 int i;
537
538 ptm.cfg.main_control = 0x00001000;
539 ptm.cfg.trigger_event = 0x0000406F;
540 ptm.cfg.te_start_stop_control = 0x00000000;
541 ptm.cfg.te_event = 0x0000006F;
542 ptm.cfg.te_control = 0x01000000;
543 ptm.cfg.fifofull_level = 0x00000028;
544 for (i = 0; i < ptm.cfg.nr_addr_comp; i++) {
545 ptm.cfg.addr_comp_value[i] = 0x00000000;
546 ptm.cfg.addr_comp_access_type[i] = 0x00000000;
547 }
548 for (i = 0; i < ptm.cfg.nr_cntr; i++) {
549 ptm.cfg.cntr_reload_value[i] = 0x00000000;
550 ptm.cfg.cntr_enable_event[i] = 0x0000406F;
551 ptm.cfg.cntr_reload_event[i] = 0x0000406F;
552 ptm.cfg.cntr_value[i] = 0x00000000;
553 }
554 ptm.cfg.seq_state_12_event = 0x0000406F;
555 ptm.cfg.seq_state_21_event = 0x0000406F;
556 ptm.cfg.seq_state_23_event = 0x0000406F;
557 ptm.cfg.seq_state_32_event = 0x0000406F;
558 ptm.cfg.seq_state_13_event = 0x0000406F;
559 ptm.cfg.seq_state_31_event = 0x0000406F;
560 ptm.cfg.current_seq_state = 0x00000000;
561 for (i = 0; i < ptm.cfg.nr_ext_output; i++)
562 ptm.cfg.ext_output_event[i] = 0x0000406F;
563 for (i = 0; i < ptm.cfg.nr_context_id_comp; i++)
564 ptm.cfg.context_id_comp_value[i] = 0x00000000;
565 ptm.cfg.context_id_comp_mask = 0x00000000;
566 ptm.cfg.sync_freq = 0x00000080;
567 ptm.cfg.extnd_ext_input_sel = 0x00000000;
568 ptm.cfg.ts_event = 0x0000406F;
569 ptm.cfg.aux_control = 0x00000000;
570 ptm.cfg.vmid_comp_value = 0x00000000;
571}
572
Pratik Patel17f3b822011-11-21 12:41:47 -0800573/* Memory mapped writes to clear os lock not supported */
574static void ptm_os_unlock(void *unused)
575{
576 unsigned long value = 0x0;
577
578 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
579 asm("isb\n\t");
580}
581
Pratik Patel7831c082011-06-08 21:44:37 -0700582static void ptm_cfg_ro_init(void)
583{
584 /* use cpu 0 for setup */
585 int cpu = 0;
586
Pratik Patel17f3b822011-11-21 12:41:47 -0800587 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel7831c082011-06-08 21:44:37 -0700588 ptm_os_unlock(NULL);
589 smp_call_function(ptm_os_unlock, NULL, 1);
590 PTM_UNLOCK(cpu);
Pratik Patel17f3b822011-11-21 12:41:47 -0800591 /* Vote for ETM power/clock enable */
Pratik Patel7831c082011-06-08 21:44:37 -0700592 ptm_clear_powerdown(cpu);
593 ptm_set_prog(cpu);
594
595 /* find all capabilities */
596 ptm.cfg.config_code = ptm_readl(ptm, cpu, ETMCCR);
597 ptm.cfg.nr_addr_comp = BMVAL(ptm.cfg.config_code, 0, 3) * 2;
598 ptm.cfg.nr_cntr = BMVAL(ptm.cfg.config_code, 13, 15);
599 ptm.cfg.nr_ext_input = BMVAL(ptm.cfg.config_code, 17, 19);
600 ptm.cfg.nr_ext_output = BMVAL(ptm.cfg.config_code, 20, 22);
601 ptm.cfg.nr_context_id_comp = BMVAL(ptm.cfg.config_code, 24, 25);
602
603 ptm.cfg.config_code_extn = ptm_readl(ptm, cpu, ETMCCER);
604 ptm.cfg.nr_extnd_ext_input_sel =
605 BMVAL(ptm.cfg.config_code_extn, 0, 2);
606 ptm.cfg.nr_instr_resources = BMVAL(ptm.cfg.config_code_extn, 13, 15);
607
608 ptm.cfg.system_config = ptm_readl(ptm, cpu, ETMSCR);
609 ptm.cfg.fifofull_supported = BVAL(ptm.cfg.system_config, 8);
610 ptm.cfg.nr_procs_supported = BMVAL(ptm.cfg.system_config, 12, 14);
611
Pratik Patel17f3b822011-11-21 12:41:47 -0800612 /* Vote for ETM power/clock disable */
Pratik Patel7831c082011-06-08 21:44:37 -0700613 ptm_set_powerdown(cpu);
614 PTM_LOCK(cpu);
615}
616
617static int __devinit ptm_probe(struct platform_device *pdev)
618{
Pratik Patele5771792011-09-17 18:33:54 -0700619 int ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700620 struct resource *res;
621
622 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
623 if (!res) {
624 ret = -EINVAL;
625 goto err_res;
626 }
627
628 ptm.base = ioremap_nocache(res->start, resource_size(res));
629 if (!ptm.base) {
630 ret = -EINVAL;
631 goto err_ioremap;
632 }
633
634 ptm.dev = &pdev->dev;
635
Pratik Patel7831c082011-06-08 21:44:37 -0700636 ret = misc_register(&ptm_misc);
637 if (ret)
638 goto err_misc;
639
Pratik Patelcc320a42011-12-22 10:48:14 -0800640 ret = qdss_clk_enable();
Pratik Patel7831c082011-06-08 21:44:37 -0700641 if (ret)
Pratik Patelcc320a42011-12-22 10:48:14 -0800642 goto err_clk;
Pratik Patel7831c082011-06-08 21:44:37 -0700643
644 ptm_cfg_ro_init();
645 ptm_cfg_rw_init();
646
647 ptm.trace_enabled = false;
648
Pratik Patel7831c082011-06-08 21:44:37 -0700649 wake_lock_init(&ptm.wake_lock, WAKE_LOCK_SUSPEND, "msm_ptm");
650 pm_qos_add_request(&ptm.qos_req, PM_QOS_CPU_DMA_LATENCY,
651 PM_QOS_DEFAULT_VALUE);
652 atomic_set(&ptm.in_use, 0);
653
Pratik Patelcc320a42011-12-22 10:48:14 -0800654 qdss_clk_disable();
Pratik Patel7831c082011-06-08 21:44:37 -0700655
656 dev_info(ptm.dev, "PTM intialized.\n");
657
658 if (trace_on_boot) {
659 if (!ptm_trace_enable())
660 dev_info(ptm.dev, "tracing enabled\n");
661 else
662 dev_err(ptm.dev, "error enabling trace\n");
663 }
664
665 return 0;
666
Pratik Patelcc320a42011-12-22 10:48:14 -0800667err_clk:
Pratik Patel7831c082011-06-08 21:44:37 -0700668 misc_deregister(&ptm_misc);
669err_misc:
Pratik Patel7831c082011-06-08 21:44:37 -0700670 iounmap(ptm.base);
671err_ioremap:
672err_res:
673 return ret;
674}
675
Pratik Patel59e29942011-12-27 10:31:33 -0800676static int ptm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700677{
678 if (ptm.trace_enabled)
679 ptm_trace_disable();
680 pm_qos_remove_request(&ptm.qos_req);
681 wake_lock_destroy(&ptm.wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700682 misc_deregister(&ptm_misc);
Pratik Patel7831c082011-06-08 21:44:37 -0700683 iounmap(ptm.base);
684
685 return 0;
686}
687
688static struct platform_driver ptm_driver = {
689 .probe = ptm_probe,
Pratik Patel59e29942011-12-27 10:31:33 -0800690 .remove = ptm_remove,
Pratik Patel7831c082011-06-08 21:44:37 -0700691 .driver = {
692 .name = "msm_ptm",
693 },
694};
695
Pratik Patel59e29942011-12-27 10:31:33 -0800696int __init ptm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700697{
698 return platform_driver_register(&ptm_driver);
699}
Pratik Patel7831c082011-06-08 21:44:37 -0700700
Pratik Patel59e29942011-12-27 10:31:33 -0800701void ptm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700702{
703 platform_driver_unregister(&ptm_driver);
704}