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