blob: 28dd1718f13951520a94ab12d71e1383a2b47b04 [file] [log] [blame]
Pratik Patel7831c082011-06-08 21:44:37 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
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>
15#include <linux/platform_device.h>
16#include <linux/io.h>
17#include <linux/err.h>
18#include <linux/fs.h>
19#include <linux/miscdevice.h>
20#include <linux/uaccess.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/smp.h>
Pratik Patel7831c082011-06-08 21:44:37 -070024#include <linux/wakelock.h>
25#include <linux/pm_qos_params.h>
26#include <linux/clk.h>
27#include <asm/atomic.h>
28
29#include "qdss.h"
30
31#define ptm_writel(ptm, cpu, val, off) \
32 __raw_writel((val), ptm.base + (SZ_4K * cpu) + off)
33#define ptm_readl(ptm, cpu, off) \
34 __raw_readl(ptm.base + (SZ_4K * cpu) + off)
35
36/*
37 * Device registers:
38 * 0x000 - 0x2FC: Trace registers
39 * 0x300 - 0x314: Management registers
40 * 0x318 - 0xEFC: Trace registers
41 *
42 * Coresight registers
43 * 0xF00 - 0xF9C: Management registers
44 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
45 * Trace registers in PFTv1.1
46 * 0xFA8 - 0xFFC: Management registers
47 */
48
49/* Trace registers (0x000-0x2FC) */
50#define ETMCR (0x000)
51#define ETMCCR (0x004)
52#define ETMTRIGGER (0x008)
53#define ETMSR (0x010)
54#define ETMSCR (0x014)
55#define ETMTSSCR (0x018)
56#define ETMTEEVR (0x020)
57#define ETMTECR1 (0x024)
58#define ETMFFLR (0x02C)
59#define ETMACVRn(n) (0x040 + (n * 4))
60#define ETMACTRn(n) (0x080 + (n * 4))
61#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
62#define ETMCNTENRn(n) (0x150 + (n * 4))
63#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
64#define ETMCNTVRn(n) (0x170 + (n * 4))
65#define ETMSQ12EVR (0x180)
66#define ETMSQ21EVR (0x184)
67#define ETMSQ23EVR (0x188)
68#define ETMSQ32EVR (0x18C)
69#define ETMSQ13EVR (0x190)
70#define ETMSQ31EVR (0x194)
71#define ETMSQR (0x19C)
72#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
73#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
74#define ETMCIDCMR (0x1BC)
75#define ETMIMPSPEC0 (0x1C0)
76#define ETMIMPSPEC1 (0x1C4)
77#define ETMIMPSPEC2 (0x1C8)
78#define ETMIMPSPEC3 (0x1CC)
79#define ETMIMPSPEC4 (0x1D0)
80#define ETMIMPSPEC5 (0x1D4)
81#define ETMIMPSPEC6 (0x1D8)
82#define ETMIMPSPEC7 (0x1DC)
83#define ETMSYNCFR (0x1E0)
84#define ETMIDR (0x1E4)
85#define ETMCCER (0x1E8)
86#define ETMEXTINSELR (0x1EC)
87#define ETMTESSEICR (0x1F0)
88#define ETMEIBCR (0x1F4)
89#define ETMTSEVR (0x1F8)
90#define ETMAUXCR (0x1FC)
91#define ETMTRACEIDR (0x200)
92#define ETMVMIDCVR (0x204)
93/* Management registers (0x300-0x314) */
94#define ETMOSLAR (0x300)
95#define ETMOSLSR (0x304)
96#define ETMOSSRR (0x308)
97#define ETMPDCR (0x310)
98#define ETMPDSR (0x314)
99
100
101#define PTM_LOCK(cpu) \
102do { \
103 mb(); \
104 ptm_writel(ptm, cpu, MAGIC2, CS_LAR); \
105} while (0)
106#define PTM_UNLOCK(cpu) \
107do { \
108 ptm_writel(ptm, cpu, MAGIC1, CS_LAR); \
109 mb(); \
110} while (0)
111
112#define PTM_OS_LOCK(cpu) \
113do { \
114 ptm_writel(ptm, cpu, MAGIC1, ETMOSLAR); \
115 mb(); \
116} while (0)
117#define PTM_OS_UNLOCK(cpu) \
118do { \
119 ptm_writel(ptm, cpu, MAGIC2, ETMOSLAR); \
120 mb(); \
121} while (0)
122
123#define MAX_TRACE_REGS (78)
124#define MAX_STATE_SIZE (MAX_TRACE_REGS * num_possible_cpus())
125
126/* Forward declarations */
127static void ptm_cfg_rw_init(void);
128
129static int trace_on_boot;
130module_param_named(
131 trace_on_boot, trace_on_boot, int, S_IRUGO
132);
133
134struct ptm_config {
135 /* read only config registers */
136 uint32_t config_code;
137 /* derived values */
138 uint8_t nr_addr_comp;
139 uint8_t nr_cntr;
140 uint8_t nr_ext_input;
141 uint8_t nr_ext_output;
142 uint8_t nr_context_id_comp;
143
144 uint32_t config_code_extn;
145 /* derived values */
146 uint8_t nr_extnd_ext_input_sel;
147 uint8_t nr_instr_resources;
148
149 uint32_t system_config;
150 /* derived values */
151 uint8_t fifofull_supported;
152 uint8_t nr_procs_supported;
153
154 /* read-write registers */
155 uint32_t main_control;
156 uint32_t trigger_event;
157 uint32_t te_start_stop_control;
158 uint32_t te_event;
159 uint32_t te_control;
160 uint32_t fifofull_level;
161 uint32_t addr_comp_value[16];
162 uint32_t addr_comp_access_type[16];
163 uint32_t cntr_reload_value[4];
164 uint32_t cntr_enable_event[4];
165 uint32_t cntr_reload_event[4];
166 uint32_t cntr_value[4];
167 uint32_t seq_state_12_event;
168 uint32_t seq_state_21_event;
169 uint32_t seq_state_23_event;
170 uint32_t seq_state_32_event;
171 uint32_t seq_state_13_event;
172 uint32_t seq_state_31_event;
173 uint32_t current_seq_state;
174 uint32_t ext_output_event[4];
175 uint32_t context_id_comp_value[3];
176 uint32_t context_id_comp_mask;
177 uint32_t sync_freq;
178 uint32_t extnd_ext_input_sel;
179 uint32_t ts_event;
180 uint32_t aux_control;
181 uint32_t coresight_trace_id;
182 uint32_t vmid_comp_value;
183};
184
185struct ptm_ctx {
186 struct ptm_config cfg;
187 void __iomem *base;
188 uint32_t *state;
189 bool trace_enabled;
Pratik Patel7831c082011-06-08 21:44:37 -0700190 struct wake_lock wake_lock;
191 struct pm_qos_request_list qos_req;
192 atomic_t in_use;
193 struct device *dev;
194 struct clk *qdss_at_clk;
195 struct clk *qdss_pclkdbg_clk;
196 struct clk *qdss_pclk;
197 struct clk *qdss_traceclkin_clk;
198 struct clk *qdss_tsctr_clk;
199};
200
201static struct ptm_ctx ptm;
202
203/* Memory mapped writes to clear os lock don't work */
204static void ptm_os_unlock(void *unused)
205{
206 unsigned long value = 0x0;
207
208 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
209 asm("isb\n\t");
210}
211
212static int ptm_clock_enable(void)
213{
214 int ret;
215
216 ret = clk_enable(ptm.qdss_at_clk);
217 if (WARN(ret, "qdss_at_clk not enabled (%d)\n", ret))
218 goto err;
219
220 ret = clk_enable(ptm.qdss_pclkdbg_clk);
221 if (WARN(ret, "qdss_pclkdbg_clk not enabled (%d)\n", ret))
222 goto err_pclkdbg;
223
224 ret = clk_enable(ptm.qdss_pclk);
225 if (WARN(ret, "qdss_pclk not enabled (%d)\n", ret))
226 goto err_pclk;
227
228 ret = clk_enable(ptm.qdss_traceclkin_clk);
229 if (WARN(ret, "qdss_traceclkin_clk not enabled (%d)\n", ret))
230 goto err_traceclkin;
231
232 ret = clk_enable(ptm.qdss_tsctr_clk);
233 if (WARN(ret, "qdss_tsctr_clk not enabled (%d)\n", ret))
234 goto err_tsctr;
235
236 return 0;
237
238err_tsctr:
239 clk_disable(ptm.qdss_traceclkin_clk);
240err_traceclkin:
241 clk_disable(ptm.qdss_pclk);
242err_pclk:
243 clk_disable(ptm.qdss_pclkdbg_clk);
244err_pclkdbg:
245 clk_disable(ptm.qdss_at_clk);
246err:
247 return ret;
248}
249
250static void ptm_clock_disable(void)
251{
252 clk_disable(ptm.qdss_tsctr_clk);
253 clk_disable(ptm.qdss_traceclkin_clk);
254 clk_disable(ptm.qdss_pclk);
255 clk_disable(ptm.qdss_pclkdbg_clk);
256 clk_disable(ptm.qdss_at_clk);
257}
258
259static void ptm_set_powerdown(int cpu)
260{
261 uint32_t etmcr;
262
263 etmcr = ptm_readl(ptm, cpu, ETMCR);
264 etmcr |= BIT(0);
265 ptm_writel(ptm, cpu, etmcr, ETMCR);
266}
267
268static void ptm_clear_powerdown(int cpu)
269{
270 uint32_t etmcr;
271
272 etmcr = ptm_readl(ptm, cpu, ETMCR);
273 etmcr &= ~BIT(0);
274 ptm_writel(ptm, cpu, etmcr, ETMCR);
275}
276
277static void ptm_set_prog(int cpu)
278{
279 uint32_t etmcr;
280 int count;
281
282 etmcr = ptm_readl(ptm, cpu, ETMCR);
283 etmcr |= BIT(10);
284 ptm_writel(ptm, cpu, etmcr, ETMCR);
285
286 for (count = TIMEOUT_US; BVAL(ptm_readl(ptm, cpu, ETMSR), 1) != 1
287 && count > 0; count--)
288 udelay(1);
289 WARN(count == 0, "timeout while setting prog bit\n");
290}
291
292static void ptm_clear_prog(int cpu)
293{
294 uint32_t etmcr;
295 int count;
296
297 etmcr = ptm_readl(ptm, cpu, ETMCR);
298 etmcr &= ~BIT(10);
299 ptm_writel(ptm, cpu, etmcr, ETMCR);
300
301 for (count = TIMEOUT_US; BVAL(ptm_readl(ptm, cpu, ETMSR), 1) != 0
302 && count > 0; count--)
303 udelay(1);
304 WARN(count == 0, "timeout while clearing prog bit\n");
305}
306
307static void __ptm_trace_enable(void)
308{
309 int i, cpu;
310
311 for_each_online_cpu(cpu) {
312 PTM_UNLOCK(cpu);
313 ptm_clear_powerdown(cpu);
314 ptm_set_prog(cpu);
315
316 ptm_writel(ptm, cpu, ptm.cfg.main_control | BIT(10), ETMCR);
317 ptm_writel(ptm, cpu, ptm.cfg.trigger_event, ETMTRIGGER);
318 ptm_writel(ptm, cpu, ptm.cfg.te_start_stop_control, ETMTSSCR);
319 ptm_writel(ptm, cpu, ptm.cfg.te_event, ETMTEEVR);
320 ptm_writel(ptm, cpu, ptm.cfg.te_control, ETMTECR1);
321 ptm_writel(ptm, cpu, ptm.cfg.fifofull_level, ETMFFLR);
322 for (i = 0; i < ptm.cfg.nr_addr_comp; i++) {
323 ptm_writel(ptm, cpu, ptm.cfg.addr_comp_value[i],
324 ETMACVRn(i));
325 ptm_writel(ptm, cpu, ptm.cfg.addr_comp_access_type[i],
326 ETMACTRn(i));
327 }
328 for (i = 0; i < ptm.cfg.nr_cntr; i++) {
329 ptm_writel(ptm, cpu, ptm.cfg.cntr_reload_value[i],
330 ETMCNTRLDVRn(i));
331 ptm_writel(ptm, cpu, ptm.cfg.cntr_enable_event[i],
332 ETMCNTENRn(i));
333 ptm_writel(ptm, cpu, ptm.cfg.cntr_reload_event[i],
334 ETMCNTRLDEVRn(i));
335 ptm_writel(ptm, cpu, ptm.cfg.cntr_value[i],
336 ETMCNTVRn(i));
337 }
338 ptm_writel(ptm, cpu, ptm.cfg.seq_state_12_event, ETMSQ12EVR);
339 ptm_writel(ptm, cpu, ptm.cfg.seq_state_21_event, ETMSQ21EVR);
340 ptm_writel(ptm, cpu, ptm.cfg.seq_state_23_event, ETMSQ23EVR);
341 ptm_writel(ptm, cpu, ptm.cfg.seq_state_32_event, ETMSQ32EVR);
342 ptm_writel(ptm, cpu, ptm.cfg.seq_state_13_event, ETMSQ13EVR);
343 ptm_writel(ptm, cpu, ptm.cfg.seq_state_31_event, ETMSQ31EVR);
344 ptm_writel(ptm, cpu, ptm.cfg.current_seq_state, ETMSQR);
345 for (i = 0; i < ptm.cfg.nr_ext_output; i++)
346 ptm_writel(ptm, cpu, ptm.cfg.ext_output_event[i],
347 ETMEXTOUTEVRn(i));
348 for (i = 0; i < ptm.cfg.nr_context_id_comp; i++)
349 ptm_writel(ptm, cpu, ptm.cfg.context_id_comp_value[i],
350 ETMCIDCVRn(i));
351 ptm_writel(ptm, cpu, ptm.cfg.context_id_comp_mask, ETMCIDCMR);
352 ptm_writel(ptm, cpu, ptm.cfg.sync_freq, ETMSYNCFR);
353 ptm_writel(ptm, cpu, ptm.cfg.extnd_ext_input_sel, ETMEXTINSELR);
354 ptm_writel(ptm, cpu, ptm.cfg.ts_event, ETMTSEVR);
355 ptm_writel(ptm, cpu, ptm.cfg.aux_control, ETMAUXCR);
356 ptm_writel(ptm, cpu, ptm.cfg.vmid_comp_value, ETMVMIDCVR);
357
358 ptm_clear_prog(cpu);
359 PTM_LOCK(cpu);
360 }
361}
362
363static int ptm_trace_enable(void)
364{
365 int ret;
366
367 ret = ptm_clock_enable();
368 if (ret)
369 return ret;
370
371 wake_lock(&ptm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700372 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700373 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700374 *
375 * we rely on the user to prevent hotplug on/off racing with this
376 * operation and to ensure cores where trace is expected to be turned
377 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700378 */
379 pm_qos_update_request(&ptm.qos_req, 0);
380
381 etb_disable();
382 tpiu_disable();
383 /* enable ETB first to avoid loosing any trace data */
384 etb_enable();
385 funnel_enable(0x0, 0x3);
386 ptm_os_unlock(NULL);
387 smp_call_function(ptm_os_unlock, NULL, 1);
388 __ptm_trace_enable();
389
390 ptm.trace_enabled = true;
391
392 pm_qos_update_request(&ptm.qos_req, PM_QOS_DEFAULT_VALUE);
393 wake_unlock(&ptm.wake_lock);
394
395 return 0;
396}
397
398static void __ptm_trace_disable(void)
399{
400 int cpu;
401
402 for_each_online_cpu(cpu) {
403 PTM_UNLOCK(cpu);
404 ptm_set_prog(cpu);
405
406 /* program trace enable to low by using always false event */
407 ptm_writel(ptm, cpu, 0x6F | BIT(14), ETMTEEVR);
408
409 ptm_set_powerdown(cpu);
410 PTM_LOCK(cpu);
411 }
412}
413
414static void ptm_trace_disable(void)
415{
Pratik Patel7831c082011-06-08 21:44:37 -0700416 wake_lock(&ptm.wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700417 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700418 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700419 *
420 * we rely on the user to prevent hotplug on/off racing with this
421 * operation and to ensure cores where trace is expected to be turned
422 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700423 */
424 pm_qos_update_request(&ptm.qos_req, 0);
425
Pratik Patel7831c082011-06-08 21:44:37 -0700426 __ptm_trace_disable();
427 etb_dump();
428 etb_disable();
429 funnel_disable(0x0, 0x3);
430
431 ptm.trace_enabled = false;
432
Pratik Patel7831c082011-06-08 21:44:37 -0700433 pm_qos_update_request(&ptm.qos_req, PM_QOS_DEFAULT_VALUE);
434 wake_unlock(&ptm.wake_lock);
435
436 ptm_clock_disable();
437}
438
439static int ptm_open(struct inode *inode, struct file *file)
440{
441 if (atomic_cmpxchg(&ptm.in_use, 0, 1))
442 return -EBUSY;
443
444 dev_dbg(ptm.dev, "%s: successfully opened\n", __func__);
445 return 0;
446}
447
448static void ptm_range_filter(char range, uint32_t reg1,
449 uint32_t addr1, uint32_t reg2, uint32_t addr2)
450{
451 ptm.cfg.addr_comp_value[reg1] = addr1;
452 ptm.cfg.addr_comp_value[reg2] = addr2;
453
454 ptm.cfg.te_control |= (1 << (reg1/2));
455 if (range == 'i')
456 ptm.cfg.te_control &= ~BIT(24);
457 else if (range == 'e')
458 ptm.cfg.te_control |= BIT(24);
459}
460
461static void ptm_start_stop_filter(char start_stop,
462 uint32_t reg, uint32_t addr)
463{
464 ptm.cfg.addr_comp_value[reg] = addr;
465
466 if (start_stop == 's')
467 ptm.cfg.te_start_stop_control |= (1 << reg);
468 else if (start_stop == 't')
469 ptm.cfg.te_start_stop_control |= (1 << (reg + 16));
470
471 ptm.cfg.te_control |= BIT(25);
472}
473
474#define MAX_COMMAND_STRLEN 40
475static ssize_t ptm_write(struct file *file, const char __user *data,
476 size_t len, loff_t *ppos)
477{
478 char command[MAX_COMMAND_STRLEN];
479 int str_len;
480 unsigned long reg1, reg2;
481 unsigned long addr1, addr2;
482
483 str_len = strnlen_user(data, MAX_COMMAND_STRLEN);
484 dev_dbg(ptm.dev, "string length: %d", str_len);
485 if (str_len == 0 || str_len == (MAX_COMMAND_STRLEN+1)) {
486 dev_err(ptm.dev, "error in str_len: %d", str_len);
487 return -EFAULT;
488 }
489 /* includes the null character */
490 if (copy_from_user(command, data, str_len)) {
491 dev_err(ptm.dev, "error in copy_from_user: %d", str_len);
492 return -EFAULT;
493 }
494
495 dev_dbg(ptm.dev, "input = %s", command);
496
497 switch (command[0]) {
498 case '0':
499 if (ptm.trace_enabled) {
500 ptm_trace_disable();
501 dev_info(ptm.dev, "tracing disabled\n");
502 } else
503 dev_err(ptm.dev, "trace already disabled\n");
504
505 break;
506 case '1':
507 if (!ptm.trace_enabled) {
508 if (!ptm_trace_enable())
509 dev_info(ptm.dev, "tracing enabled\n");
510 else
511 dev_err(ptm.dev, "error enabling trace\n");
512 } else
513 dev_err(ptm.dev, "trace already enabled\n");
514 break;
515 case 'f':
516 switch (command[2]) {
517 case 'i':
518 switch (command[4]) {
519 case 'i':
520 if (sscanf(&command[6], "%lx:%lx:%lx:%lx\\0",
521 &reg1, &addr1, &reg2, &addr2) != 4)
522 goto err_out;
523 if (reg1 > 7 || reg2 > 7 || (reg1 % 2))
524 goto err_out;
525 ptm_range_filter('i',
526 reg1, addr1, reg2, addr2);
527 break;
528 case 'e':
529 if (sscanf(&command[6], "%lx:%lx:%lx:%lx\\0",
530 &reg1, &addr1, &reg2, &addr2) != 4)
531 goto err_out;
532 if (reg1 > 7 || reg2 > 7 || (reg1 % 2)
533 || command[2] == 'd')
534 goto err_out;
535 ptm_range_filter('e',
536 reg1, addr1, reg2, addr2);
537 break;
538 case 's':
539 if (sscanf(&command[6], "%lx:%lx\\0",
540 &reg1, &addr1) != 2)
541 goto err_out;
542 if (reg1 > 7)
543 goto err_out;
544 ptm_start_stop_filter('s', reg1, addr1);
545 break;
546 case 't':
547 if (sscanf(&command[6], "%lx:%lx\\0",
548 &reg1, &addr1) != 2)
549 goto err_out;
550 if (reg1 > 7)
551 goto err_out;
552 ptm_start_stop_filter('t', reg1, addr1);
553 break;
554 default:
555 goto err_out;
556 }
557 break;
558 case 'r':
559 ptm_cfg_rw_init();
560 break;
561 default:
562 goto err_out;
563 }
564 break;
565 default:
566 goto err_out;
567 }
568
569 return len;
570
571err_out:
572 return -EFAULT;
573}
574
575static int ptm_release(struct inode *inode, struct file *file)
576{
577 atomic_set(&ptm.in_use, 0);
578 dev_dbg(ptm.dev, "%s: released\n", __func__);
579 return 0;
580}
581
582static const struct file_operations ptm_fops = {
583 .owner = THIS_MODULE,
584 .open = ptm_open,
585 .write = ptm_write,
586 .release = ptm_release,
587};
588
589static struct miscdevice ptm_misc = {
590 .name = "msm_ptm",
591 .minor = MISC_DYNAMIC_MINOR,
592 .fops = &ptm_fops,
593};
594
595static void ptm_save_reg(int cpu)
596{
597 uint32_t i;
598 int j;
599
600 PTM_UNLOCK(cpu);
601
602 i = cpu * MAX_TRACE_REGS;
603
604 ptm.state[i++] = ptm_readl(ptm, cpu, ETMCR);
605 ptm_set_prog(cpu);
606
607 ptm.state[i++] = ptm_readl(ptm, cpu, ETMTRIGGER);
608 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSR);
609 ptm.state[i++] = ptm_readl(ptm, cpu, ETMTSSCR);
610 ptm.state[i++] = ptm_readl(ptm, cpu, ETMTEEVR);
611 ptm.state[i++] = ptm_readl(ptm, cpu, ETMTECR1);
612 ptm.state[i++] = ptm_readl(ptm, cpu, ETMFFLR);
613 for (j = 0; j < ptm.cfg.nr_addr_comp; j++) {
614 ptm.state[i++] = ptm_readl(ptm, cpu, ETMACVRn(j));
615 ptm.state[i++] = ptm_readl(ptm, cpu, ETMACTRn(j));
616 }
617 for (j = 0; j < ptm.cfg.nr_cntr; j++) {
618 ptm.state[i++] = ptm_readl(ptm, cpu, ETMCNTRLDVRn(j));
619 ptm.state[i++] = ptm_readl(ptm, cpu, ETMCNTENRn(j));
620 ptm.state[i++] = ptm_readl(ptm, cpu, ETMCNTRLDEVRn(j));
621 ptm.state[i++] = ptm_readl(ptm, cpu, ETMCNTVRn(j));
622 }
623 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSQ12EVR);
624 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSQ21EVR);
625 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSQ23EVR);
626 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSQ32EVR);
627 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSQ13EVR);
628 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSQ31EVR);
629 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSQR);
630 for (j = 0; j < ptm.cfg.nr_ext_output; j++)
631 ptm.state[i++] = ptm_readl(ptm, cpu, ETMEXTOUTEVRn(j));
632 for (j = 0; j < ptm.cfg.nr_context_id_comp; j++)
633 ptm.state[i++] = ptm_readl(ptm, cpu, ETMCIDCVRn(j));
634 ptm.state[i++] = ptm_readl(ptm, cpu, ETMCIDCMR);
635 ptm.state[i++] = ptm_readl(ptm, cpu, ETMSYNCFR);
636 ptm.state[i++] = ptm_readl(ptm, cpu, ETMEXTINSELR);
637 ptm.state[i++] = ptm_readl(ptm, cpu, ETMTSEVR);
638 ptm.state[i++] = ptm_readl(ptm, cpu, ETMAUXCR);
639 ptm.state[i++] = ptm_readl(ptm, cpu, ETMVMIDCVR);
640 ptm.state[i++] = ptm_readl(ptm, cpu, CS_CLAIMSET);
641 ptm.state[i++] = ptm_readl(ptm, cpu, CS_CLAIMCLR);
642
643 PTM_LOCK(cpu);
644}
645
646static void ptm_restore_reg(int cpu)
647{
648 uint32_t i;
649 int j;
650
651 ptm_os_unlock(NULL);
652 PTM_UNLOCK(cpu);
653
654 i = cpu * MAX_TRACE_REGS;
655
656 ptm_clear_powerdown(cpu);
657 ptm_set_prog(cpu);
658 /* Ensure prog bit doesn't get cleared since we have set it above.
659 * Power down bit should already be clear in the saved state.
660 */
661 ptm_writel(ptm, cpu, ptm.state[i++] | BIT(10), ETMCR);
662
663 ptm_writel(ptm, cpu, ptm.state[i++], ETMTRIGGER);
664 ptm_writel(ptm, cpu, ptm.state[i++], ETMSR);
665 ptm_writel(ptm, cpu, ptm.state[i++], ETMTSSCR);
666 ptm_writel(ptm, cpu, ptm.state[i++], ETMTEEVR);
667 ptm_writel(ptm, cpu, ptm.state[i++], ETMTECR1);
668 ptm_writel(ptm, cpu, ptm.state[i++], ETMFFLR);
669 for (j = 0; j < ptm.cfg.nr_addr_comp; j++) {
670 ptm_writel(ptm, cpu, ptm.state[i++], ETMACVRn(j));
671 ptm_writel(ptm, cpu, ptm.state[i++], ETMACTRn(j));
672 }
673 for (j = 0; j < ptm.cfg.nr_cntr; j++) {
674 ptm_writel(ptm, cpu, ptm.state[i++], ETMCNTRLDVRn(j));
675 ptm_writel(ptm, cpu, ptm.state[i++], ETMCNTENRn(j));
676 ptm_writel(ptm, cpu, ptm.state[i++], ETMCNTRLDEVRn(j));
677 ptm_writel(ptm, cpu, ptm.state[i++], ETMCNTVRn(j));
678 }
679 ptm_writel(ptm, cpu, ptm.state[i++], ETMSQ12EVR);
680 ptm_writel(ptm, cpu, ptm.state[i++], ETMSQ21EVR);
681 ptm_writel(ptm, cpu, ptm.state[i++], ETMSQ23EVR);
682 ptm_writel(ptm, cpu, ptm.state[i++], ETMSQ32EVR);
683 ptm_writel(ptm, cpu, ptm.state[i++], ETMSQ13EVR);
684 ptm_writel(ptm, cpu, ptm.state[i++], ETMSQ31EVR);
685 ptm_writel(ptm, cpu, ptm.state[i++], ETMSQR);
686 for (j = 0; j < ptm.cfg.nr_ext_output; j++)
687 ptm_writel(ptm, cpu, ptm.state[i++], ETMEXTOUTEVRn(j));
688 for (j = 0; j < ptm.cfg.nr_context_id_comp; j++)
689 ptm_writel(ptm, cpu, ptm.state[i++], ETMCIDCVRn(j));
690 ptm_writel(ptm, cpu, ptm.state[i++], ETMCIDCMR);
691 ptm_writel(ptm, cpu, ptm.state[i++], ETMSYNCFR);
692 ptm_writel(ptm, cpu, ptm.state[i++], ETMEXTINSELR);
693 ptm_writel(ptm, cpu, ptm.state[i++], ETMTSEVR);
694 ptm_writel(ptm, cpu, ptm.state[i++], ETMAUXCR);
695 ptm_writel(ptm, cpu, ptm.state[i++], ETMVMIDCVR);
696 ptm_writel(ptm, cpu, ptm.state[i++], CS_CLAIMSET);
697 ptm_writel(ptm, cpu, ptm.state[i++], CS_CLAIMCLR);
698
699 ptm_clear_prog(cpu);
700
701 PTM_LOCK(cpu);
702}
703
704/* etm_save_reg_check and etm_restore_reg_check should be fast
705 *
706 * These functions will be called either from:
707 * 1. per_cpu idle thread context for idle power collapses.
708 * 2. per_cpu idle thread context for hotplug/suspend power collapse for
709 * nonboot cpus.
710 * 3. suspend thread context for core0.
711 *
712 * In all cases we are guaranteed to be running on the same cpu for the
713 * entire duration.
714 *
715 * Another assumption is that etm registers won't change after trace_enabled
716 * is set. Current usage model guarantees this doesn't happen.
Pratik Patele5771792011-09-17 18:33:54 -0700717 *
718 * Also disabling all types of power_collapses when enabling and disabling
719 * trace provides mutual exclusion to be able to safely access
720 * ptm.trace_enabled here.
Pratik Patel7831c082011-06-08 21:44:37 -0700721 */
722void etm_save_reg_check(void)
723{
Pratik Patel7831c082011-06-08 21:44:37 -0700724 if (ptm.trace_enabled) {
725 int cpu = smp_processor_id();
Pratik Patele5771792011-09-17 18:33:54 -0700726 ptm_save_reg(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700727 }
728}
729
730void etm_restore_reg_check(void)
731{
Pratik Patel7831c082011-06-08 21:44:37 -0700732 if (ptm.trace_enabled) {
733 int cpu = smp_processor_id();
Pratik Patel7831c082011-06-08 21:44:37 -0700734 ptm_restore_reg(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700735 }
736}
737
738static void ptm_cfg_rw_init(void)
739{
740 int i;
741
742 ptm.cfg.main_control = 0x00001000;
743 ptm.cfg.trigger_event = 0x0000406F;
744 ptm.cfg.te_start_stop_control = 0x00000000;
745 ptm.cfg.te_event = 0x0000006F;
746 ptm.cfg.te_control = 0x01000000;
747 ptm.cfg.fifofull_level = 0x00000028;
748 for (i = 0; i < ptm.cfg.nr_addr_comp; i++) {
749 ptm.cfg.addr_comp_value[i] = 0x00000000;
750 ptm.cfg.addr_comp_access_type[i] = 0x00000000;
751 }
752 for (i = 0; i < ptm.cfg.nr_cntr; i++) {
753 ptm.cfg.cntr_reload_value[i] = 0x00000000;
754 ptm.cfg.cntr_enable_event[i] = 0x0000406F;
755 ptm.cfg.cntr_reload_event[i] = 0x0000406F;
756 ptm.cfg.cntr_value[i] = 0x00000000;
757 }
758 ptm.cfg.seq_state_12_event = 0x0000406F;
759 ptm.cfg.seq_state_21_event = 0x0000406F;
760 ptm.cfg.seq_state_23_event = 0x0000406F;
761 ptm.cfg.seq_state_32_event = 0x0000406F;
762 ptm.cfg.seq_state_13_event = 0x0000406F;
763 ptm.cfg.seq_state_31_event = 0x0000406F;
764 ptm.cfg.current_seq_state = 0x00000000;
765 for (i = 0; i < ptm.cfg.nr_ext_output; i++)
766 ptm.cfg.ext_output_event[i] = 0x0000406F;
767 for (i = 0; i < ptm.cfg.nr_context_id_comp; i++)
768 ptm.cfg.context_id_comp_value[i] = 0x00000000;
769 ptm.cfg.context_id_comp_mask = 0x00000000;
770 ptm.cfg.sync_freq = 0x00000080;
771 ptm.cfg.extnd_ext_input_sel = 0x00000000;
772 ptm.cfg.ts_event = 0x0000406F;
773 ptm.cfg.aux_control = 0x00000000;
774 ptm.cfg.vmid_comp_value = 0x00000000;
775}
776
777static void ptm_cfg_ro_init(void)
778{
779 /* use cpu 0 for setup */
780 int cpu = 0;
781
782 ptm_os_unlock(NULL);
783 smp_call_function(ptm_os_unlock, NULL, 1);
784 PTM_UNLOCK(cpu);
785 ptm_clear_powerdown(cpu);
786 ptm_set_prog(cpu);
787
788 /* find all capabilities */
789 ptm.cfg.config_code = ptm_readl(ptm, cpu, ETMCCR);
790 ptm.cfg.nr_addr_comp = BMVAL(ptm.cfg.config_code, 0, 3) * 2;
791 ptm.cfg.nr_cntr = BMVAL(ptm.cfg.config_code, 13, 15);
792 ptm.cfg.nr_ext_input = BMVAL(ptm.cfg.config_code, 17, 19);
793 ptm.cfg.nr_ext_output = BMVAL(ptm.cfg.config_code, 20, 22);
794 ptm.cfg.nr_context_id_comp = BMVAL(ptm.cfg.config_code, 24, 25);
795
796 ptm.cfg.config_code_extn = ptm_readl(ptm, cpu, ETMCCER);
797 ptm.cfg.nr_extnd_ext_input_sel =
798 BMVAL(ptm.cfg.config_code_extn, 0, 2);
799 ptm.cfg.nr_instr_resources = BMVAL(ptm.cfg.config_code_extn, 13, 15);
800
801 ptm.cfg.system_config = ptm_readl(ptm, cpu, ETMSCR);
802 ptm.cfg.fifofull_supported = BVAL(ptm.cfg.system_config, 8);
803 ptm.cfg.nr_procs_supported = BMVAL(ptm.cfg.system_config, 12, 14);
804
805 ptm_set_powerdown(cpu);
806 PTM_LOCK(cpu);
807}
808
809static int __devinit ptm_probe(struct platform_device *pdev)
810{
Pratik Patele5771792011-09-17 18:33:54 -0700811 int ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700812 struct resource *res;
813
814 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
815 if (!res) {
816 ret = -EINVAL;
817 goto err_res;
818 }
819
820 ptm.base = ioremap_nocache(res->start, resource_size(res));
821 if (!ptm.base) {
822 ret = -EINVAL;
823 goto err_ioremap;
824 }
825
826 ptm.dev = &pdev->dev;
827
828 ptm.state = kzalloc(MAX_STATE_SIZE * sizeof(uint32_t), GFP_KERNEL);
829 if (!ptm.state) {
830 ret = -ENOMEM;
831 goto err_kzalloc;
832 }
833
834 ret = misc_register(&ptm_misc);
835 if (ret)
836 goto err_misc;
837
838 ptm.qdss_at_clk = clk_get(NULL, "qdss_at_clk");
839 if (IS_ERR(ptm.qdss_at_clk)) {
840 ret = PTR_ERR(ptm.qdss_at_clk);
841 goto err_at;
842 }
843 ret = clk_set_rate(ptm.qdss_at_clk, 300000000);
844 if (ret)
845 goto err_at_rate;
846 ret = clk_enable(ptm.qdss_at_clk);
847 if (ret)
848 goto err_at_enable;
849
850 ptm.qdss_pclkdbg_clk = clk_get(NULL, "qdss_pclkdbg_clk");
851 if (IS_ERR(ptm.qdss_pclkdbg_clk)) {
852 ret = PTR_ERR(ptm.qdss_pclkdbg_clk);
853 goto err_pclkdbg;
854 }
855 ret = clk_enable(ptm.qdss_pclkdbg_clk);
856 if (ret)
857 goto err_pclkdbg_enable;
858
859 ptm.qdss_pclk = clk_get(NULL, "qdss_pclk");
860 if (IS_ERR(ptm.qdss_pclk)) {
861 ret = PTR_ERR(ptm.qdss_pclk);
862 goto err_pclk;
863 }
864
865 ret = clk_enable(ptm.qdss_pclk);
866 if (ret)
867 goto err_pclk_enable;
868
869 ptm.qdss_traceclkin_clk = clk_get(NULL, "qdss_traceclkin_clk");
870 if (IS_ERR(ptm.qdss_traceclkin_clk)) {
871 ret = PTR_ERR(ptm.qdss_traceclkin_clk);
872 goto err_traceclkin;
873 }
874 ret = clk_set_rate(ptm.qdss_traceclkin_clk, 300000000);
875 if (ret)
876 goto err_traceclkin_rate;
877 ret = clk_enable(ptm.qdss_traceclkin_clk);
878 if (ret)
879 goto err_traceclkin_enable;
880
881 ptm.qdss_tsctr_clk = clk_get(NULL, "qdss_tsctr_clk");
882 if (IS_ERR(ptm.qdss_tsctr_clk)) {
883 ret = PTR_ERR(ptm.qdss_tsctr_clk);
884 goto err_tsctr;
885 }
886 ret = clk_set_rate(ptm.qdss_tsctr_clk, 400000000);
887 if (ret)
888 goto err_tsctr_rate;
889
890 ret = clk_enable(ptm.qdss_tsctr_clk);
891 if (ret)
892 goto err_tsctr_enable;
893
894 ptm_cfg_ro_init();
895 ptm_cfg_rw_init();
896
897 ptm.trace_enabled = false;
898
Pratik Patel7831c082011-06-08 21:44:37 -0700899 wake_lock_init(&ptm.wake_lock, WAKE_LOCK_SUSPEND, "msm_ptm");
900 pm_qos_add_request(&ptm.qos_req, PM_QOS_CPU_DMA_LATENCY,
901 PM_QOS_DEFAULT_VALUE);
902 atomic_set(&ptm.in_use, 0);
903
904 clk_disable(ptm.qdss_tsctr_clk);
905 clk_disable(ptm.qdss_traceclkin_clk);
906 clk_disable(ptm.qdss_pclk);
907 clk_disable(ptm.qdss_pclkdbg_clk);
908 clk_disable(ptm.qdss_at_clk);
909
910 dev_info(ptm.dev, "PTM intialized.\n");
911
912 if (trace_on_boot) {
913 if (!ptm_trace_enable())
914 dev_info(ptm.dev, "tracing enabled\n");
915 else
916 dev_err(ptm.dev, "error enabling trace\n");
917 }
918
919 return 0;
920
Pratik Patel7831c082011-06-08 21:44:37 -0700921err_tsctr_enable:
922err_tsctr_rate:
923 clk_put(ptm.qdss_tsctr_clk);
924err_tsctr:
925 clk_disable(ptm.qdss_traceclkin_clk);
926err_traceclkin_enable:
927err_traceclkin_rate:
928 clk_put(ptm.qdss_traceclkin_clk);
929err_traceclkin:
930 clk_disable(ptm.qdss_pclk);
931err_pclk_enable:
932 clk_put(ptm.qdss_pclk);
933err_pclk:
934 clk_disable(ptm.qdss_pclkdbg_clk);
935err_pclkdbg_enable:
936 clk_put(ptm.qdss_pclkdbg_clk);
937err_pclkdbg:
938 clk_disable(ptm.qdss_at_clk);
939err_at_enable:
940err_at_rate:
941 clk_put(ptm.qdss_at_clk);
942err_at:
943 misc_deregister(&ptm_misc);
944err_misc:
945 kfree(ptm.state);
946err_kzalloc:
947 iounmap(ptm.base);
948err_ioremap:
949err_res:
950 return ret;
951}
952
953static int __devexit ptm_remove(struct platform_device *pdev)
954{
955 if (ptm.trace_enabled)
956 ptm_trace_disable();
957 pm_qos_remove_request(&ptm.qos_req);
958 wake_lock_destroy(&ptm.wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700959 clk_put(ptm.qdss_tsctr_clk);
960 clk_put(ptm.qdss_traceclkin_clk);
961 clk_put(ptm.qdss_pclk);
962 clk_put(ptm.qdss_pclkdbg_clk);
963 clk_put(ptm.qdss_at_clk);
964 misc_deregister(&ptm_misc);
965 kfree(ptm.state);
966 iounmap(ptm.base);
967
968 return 0;
969}
970
971static struct platform_driver ptm_driver = {
972 .probe = ptm_probe,
973 .remove = __devexit_p(ptm_remove),
974 .driver = {
975 .name = "msm_ptm",
976 },
977};
978
979static int __init ptm_init(void)
980{
981 return platform_driver_register(&ptm_driver);
982}
983module_init(ptm_init);
984
985static void __exit ptm_exit(void)
986{
987 platform_driver_unregister(&ptm_driver);
988}
989module_exit(ptm_exit);
990
991MODULE_LICENSE("GPL v2");
992MODULE_DESCRIPTION("Coresight Program Flow Trace driver");