blob: c501700342cfbc2fef85595a412dedae350d9128 [file] [log] [blame]
Pratik Patel8c86adf2012-12-07 13:42:12 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Pratik Patel22911492012-06-25 21:38:02 -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>
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/device.h>
18#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/memory_alloc.h>
26#include <linux/delay.h>
27#include <linux/spinlock.h>
28#include <linux/clk.h>
Pratik Patel8c86adf2012-12-07 13:42:12 -080029#include <linux/of.h>
Pratik Patel22911492012-06-25 21:38:02 -070030#include <linux/of_coresight.h>
31#include <linux/coresight.h>
Pratik Patel7c0b3722013-02-08 11:57:27 -080032#include <linux/coresight-cti.h>
Pushkar Joshibf213a02013-05-03 13:18:44 -070033#include <linux/wait.h>
34#include <linux/sched.h>
35#include <linux/interrupt.h>
36#include <linux/cdev.h>
Pratik Patelb46038f2012-07-22 23:09:11 -070037#include <linux/usb/usb_qdss.h>
Pratik Patel22911492012-06-25 21:38:02 -070038#include <mach/memory.h>
Pratik Patelb46038f2012-07-22 23:09:11 -070039#include <mach/sps.h>
40#include <mach/usb_bam.h>
Pratik Patel26477792012-09-07 01:35:36 -070041#include <mach/msm_memory_dump.h>
Pratik Patel22911492012-06-25 21:38:02 -070042
43#include "coresight-priv.h"
44
Pratik Patel22911492012-06-25 21:38:02 -070045#define tmc_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
46#define tmc_readl(drvdata, off) __raw_readl(drvdata->base + off)
47
48#define TMC_LOCK(drvdata) \
49do { \
50 mb(); \
51 tmc_writel(drvdata, 0x0, CORESIGHT_LAR); \
52} while (0)
53#define TMC_UNLOCK(drvdata) \
54do { \
55 tmc_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
56 mb(); \
57} while (0)
58
Pratik Patel84750b22012-12-11 21:56:19 -080059#define TMC_RSZ (0x004)
60#define TMC_STS (0x00C)
61#define TMC_RRD (0x010)
62#define TMC_RRP (0x014)
63#define TMC_RWP (0x018)
64#define TMC_TRG (0x01C)
65#define TMC_CTL (0x020)
66#define TMC_RWD (0x024)
67#define TMC_MODE (0x028)
68#define TMC_LBUFLEVEL (0x02C)
69#define TMC_CBUFLEVEL (0x030)
70#define TMC_BUFWM (0x034)
71#define TMC_RRPHI (0x038)
72#define TMC_RWPHI (0x03C)
73#define TMC_AXICTL (0x110)
74#define TMC_DBALO (0x118)
75#define TMC_DBAHI (0x11C)
76#define TMC_FFSR (0x300)
77#define TMC_FFCR (0x304)
78#define TMC_PSCR (0x308)
79#define TMC_ITMISCOP0 (0xEE0)
80#define TMC_ITTRFLIN (0xEE8)
81#define TMC_ITATBDATA0 (0xEEC)
82#define TMC_ITATBCTR2 (0xEF0)
83#define TMC_ITATBCTR1 (0xEF4)
84#define TMC_ITATBCTR0 (0xEF8)
Pratik Patel22911492012-06-25 21:38:02 -070085
Pratik Patel84750b22012-12-11 21:56:19 -080086#define BYTES_PER_WORD 4
87#define TMC_ETR_BAM_PIPE_INDEX 0
88#define TMC_ETR_BAM_NR_PIPES 2
Pratik Patel22911492012-06-25 21:38:02 -070089
Pratik Patel84750b22012-12-11 21:56:19 -080090#define TMC_ETFETB_DUMP_MAGIC_OFF (0)
91#define TMC_ETFETB_DUMP_MAGIC (0x5D1DB1BF)
92#define TMC_ETFETB_DUMP_VER_OFF (4)
93#define TMC_ETFETB_DUMP_VER (1)
94#define TMC_REG_DUMP_MAGIC_OFF (0)
95#define TMC_REG_DUMP_MAGIC (0x5D1DB1BF)
96#define TMC_REG_DUMP_VER_OFF (4)
97#define TMC_REG_DUMP_VER (1)
Pratik Patel26477792012-09-07 01:35:36 -070098
Pratik Patel22911492012-06-25 21:38:02 -070099enum tmc_config_type {
100 TMC_CONFIG_TYPE_ETB,
101 TMC_CONFIG_TYPE_ETR,
102 TMC_CONFIG_TYPE_ETF,
103};
104
105enum tmc_mode {
106 TMC_MODE_CIRCULAR_BUFFER,
107 TMC_MODE_SOFTWARE_FIFO,
108 TMC_MODE_HARDWARE_FIFO,
109};
110
Pratik Patelb46038f2012-07-22 23:09:11 -0700111enum tmc_etr_out_mode {
112 TMC_ETR_OUT_MODE_NONE,
113 TMC_ETR_OUT_MODE_MEM,
114 TMC_ETR_OUT_MODE_USB,
115};
116
Pratik Patel22911492012-06-25 21:38:02 -0700117enum tmc_mem_intf_width {
118 TMC_MEM_INTF_WIDTH_32BITS = 0x2,
119 TMC_MEM_INTF_WIDTH_64BITS = 0x3,
120 TMC_MEM_INTF_WIDTH_128BITS = 0x4,
121 TMC_MEM_INTF_WIDTH_256BITS = 0x5,
122};
123
Pratik Patelb46038f2012-07-22 23:09:11 -0700124struct tmc_etr_bam_data {
125 struct sps_bam_props props;
126 uint32_t handle;
127 struct sps_pipe *pipe;
128 struct sps_connect connect;
129 uint32_t src_pipe_idx;
130 uint32_t dest;
131 uint32_t dest_pipe_idx;
132 struct sps_mem_buffer desc_fifo;
133 struct sps_mem_buffer data_fifo;
134 bool enable;
135};
136
Pratik Patel22911492012-06-25 21:38:02 -0700137struct tmc_drvdata {
138 void __iomem *base;
139 struct device *dev;
140 struct coresight_device *csdev;
141 struct miscdevice miscdev;
Pushkar Joshibf213a02013-05-03 13:18:44 -0700142 struct cdev byte_cntr_dev;
143 struct class *byte_cntr_class;
Pratik Patel22911492012-06-25 21:38:02 -0700144 struct clk *clk;
145 spinlock_t spinlock;
Pratik Patela5544162013-02-08 11:57:27 -0800146 bool reset_flush_race;
Pratik Patel7c0b3722013-02-08 11:57:27 -0800147 struct coresight_cti *cti_flush;
148 struct coresight_cti *cti_reset;
Pratik Patelb46038f2012-07-22 23:09:11 -0700149 struct mutex read_lock;
Pratik Patel22911492012-06-25 21:38:02 -0700150 int read_count;
151 bool reading;
Pratik Patel84750b22012-12-11 21:56:19 -0800152 bool aborting;
153 char *reg_buf;
Pratik Patel22911492012-06-25 21:38:02 -0700154 char *buf;
155 unsigned long paddr;
156 void __iomem *vaddr;
157 uint32_t size;
Pratik Patelb46038f2012-07-22 23:09:11 -0700158 struct mutex usb_lock;
159 struct usb_qdss_ch *usbch;
160 struct tmc_etr_bam_data *bamdata;
161 enum tmc_etr_out_mode out_mode;
162 bool enable_to_bam;
Pratik Patel22911492012-06-25 21:38:02 -0700163 bool enable;
164 enum tmc_config_type config_type;
165 uint32_t trigger_cntr;
Pushkar Joshibf213a02013-05-03 13:18:44 -0700166 int byte_cntr_irq;
167 atomic_t byte_cntr_irq_cnt;
168 uint32_t byte_cntr_value;
169 struct mutex byte_cntr_read_lock;
170 struct mutex byte_cntr_lock;
171 uint32_t byte_cntr_block_size;
172 bool byte_cntr_overflow;
173 bool byte_cntr_present;
174 bool byte_cntr_enable;
175 uint32_t byte_cntr_overflow_cnt;
176 bool byte_cntr_read_active;
177 wait_queue_head_t wq;
178 char *byte_cntr_node;
Pratik Patel22911492012-06-25 21:38:02 -0700179};
180
Pratik Patelbfd2de62013-01-26 12:14:59 -0800181static void tmc_wait_for_flush(struct tmc_drvdata *drvdata)
182{
183 int count;
184
185 /* Ensure no flush is in progress */
186 for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_FFSR), 0) != 0
187 && count > 0; count--)
188 udelay(1);
189 WARN(count == 0, "timeout while waiting for TMC flush, TMC_FFSR: %#x\n",
190 tmc_readl(drvdata, TMC_FFSR));
191}
192
Pratik Patel22911492012-06-25 21:38:02 -0700193static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
194{
195 int count;
196
197 /* Ensure formatter, unformatter and hardware fifo are empty */
198 for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_STS), 2) != 1
199 && count > 0; count--)
200 udelay(1);
201 WARN(count == 0, "timeout while waiting for TMC ready, TMC_STS: %#x\n",
202 tmc_readl(drvdata, TMC_STS));
203}
204
205static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
206{
207 int count;
208 uint32_t ffcr;
209
210 ffcr = tmc_readl(drvdata, TMC_FFCR);
211 ffcr |= BIT(12);
212 tmc_writel(drvdata, ffcr, TMC_FFCR);
213 ffcr |= BIT(6);
214 tmc_writel(drvdata, ffcr, TMC_FFCR);
215 /* Ensure flush completes */
216 for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_FFCR), 6) != 0
217 && count > 0; count--)
218 udelay(1);
219 WARN(count == 0, "timeout while flushing TMC, TMC_FFCR: %#x\n",
220 tmc_readl(drvdata, TMC_FFCR));
221
222 tmc_wait_for_ready(drvdata);
223}
224
225static void __tmc_enable(struct tmc_drvdata *drvdata)
226{
227 tmc_writel(drvdata, 0x1, TMC_CTL);
228}
229
230static void __tmc_disable(struct tmc_drvdata *drvdata)
231{
232 tmc_writel(drvdata, 0x0, TMC_CTL);
233}
234
Pratik Patelb46038f2012-07-22 23:09:11 -0700235static void tmc_etr_fill_usb_bam_data(struct tmc_drvdata *drvdata)
236{
237 struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
238
Shimrit Malichidbf43d72013-03-16 03:32:27 +0200239 get_bam2bam_connection_info(usb_bam_get_qdss_idx(0),
Pratik Patelb46038f2012-07-22 23:09:11 -0700240 &bamdata->dest,
241 &bamdata->dest_pipe_idx,
242 &bamdata->src_pipe_idx,
243 &bamdata->desc_fifo,
244 &bamdata->data_fifo);
245}
246
247static void __tmc_etr_enable_to_bam(struct tmc_drvdata *drvdata)
248{
249 struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
250 uint32_t axictl;
251
252 if (drvdata->enable_to_bam)
253 return;
254
255 /* Configure and enable required CSR registers */
256 msm_qdss_csr_enable_bam_to_usb();
257
258 /* Configure and enable ETR for usb bam output */
259
260 TMC_UNLOCK(drvdata);
261
262 tmc_writel(drvdata, bamdata->data_fifo.size / BYTES_PER_WORD,
263 TMC_RSZ);
264 tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
265
266 axictl = tmc_readl(drvdata, TMC_AXICTL);
267 axictl |= (0xF << 8);
268 tmc_writel(drvdata, axictl, TMC_AXICTL);
269 axictl &= ~(0x1 << 7);
270 tmc_writel(drvdata, axictl, TMC_AXICTL);
271 axictl = (axictl & ~0x3) | 0x2;
272 tmc_writel(drvdata, axictl, TMC_AXICTL);
273
274 tmc_writel(drvdata, bamdata->data_fifo.phys_base, TMC_DBALO);
275 tmc_writel(drvdata, 0x0, TMC_DBAHI);
Pratik Patelbfd2de62013-01-26 12:14:59 -0800276 tmc_writel(drvdata, 0x103, TMC_FFCR);
Pratik Patelb46038f2012-07-22 23:09:11 -0700277 tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
278 __tmc_enable(drvdata);
279
280 TMC_LOCK(drvdata);
281
282 drvdata->enable_to_bam = true;
283}
284
285static int tmc_etr_bam_enable(struct tmc_drvdata *drvdata)
286{
287 struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
288 int ret;
289
290 if (bamdata->enable)
291 return 0;
292
Pratik Patelaa0e6f92013-01-26 11:21:03 -0800293 /* Reset bam to start with */
294 ret = sps_device_reset(bamdata->handle);
295 if (ret)
296 goto err0;
297
298 /* Now configure and enable bam */
Pratik Patelb46038f2012-07-22 23:09:11 -0700299
300 bamdata->pipe = sps_alloc_endpoint();
301 if (!bamdata->pipe)
302 return -ENOMEM;
303
304 ret = sps_get_config(bamdata->pipe, &bamdata->connect);
305 if (ret)
Pratik Patelaa0e6f92013-01-26 11:21:03 -0800306 goto err1;
Pratik Patelb46038f2012-07-22 23:09:11 -0700307
308 bamdata->connect.mode = SPS_MODE_SRC;
309 bamdata->connect.source = bamdata->handle;
310 bamdata->connect.event_thresh = 0x4;
311 bamdata->connect.src_pipe_index = TMC_ETR_BAM_PIPE_INDEX;
312 bamdata->connect.options = SPS_O_AUTO_ENABLE;
313
314 bamdata->connect.destination = bamdata->dest;
315 bamdata->connect.dest_pipe_index = bamdata->dest_pipe_idx;
316 bamdata->connect.desc = bamdata->desc_fifo;
317 bamdata->connect.data = bamdata->data_fifo;
318
319 ret = sps_connect(bamdata->pipe, &bamdata->connect);
320 if (ret)
Pratik Patelaa0e6f92013-01-26 11:21:03 -0800321 goto err1;
Pratik Patelb46038f2012-07-22 23:09:11 -0700322
323 bamdata->enable = true;
324 return 0;
Pratik Patelaa0e6f92013-01-26 11:21:03 -0800325err1:
Pratik Patelb46038f2012-07-22 23:09:11 -0700326 sps_free_endpoint(bamdata->pipe);
Pratik Patelaa0e6f92013-01-26 11:21:03 -0800327err0:
Pratik Patelb46038f2012-07-22 23:09:11 -0700328 return ret;
329}
330
331static void __tmc_etr_disable_to_bam(struct tmc_drvdata *drvdata)
332{
333 if (!drvdata->enable_to_bam)
334 return;
335
Pratik Patelbfd2de62013-01-26 12:14:59 -0800336 /* Ensure periodic flush is disabled in CSR block */
337 msm_qdss_csr_disable_flush();
338
Pratik Patelb46038f2012-07-22 23:09:11 -0700339 TMC_UNLOCK(drvdata);
340
Pratik Patelbfd2de62013-01-26 12:14:59 -0800341 tmc_wait_for_flush(drvdata);
Pratik Patelb46038f2012-07-22 23:09:11 -0700342 tmc_flush_and_stop(drvdata);
343 __tmc_disable(drvdata);
344
345 TMC_LOCK(drvdata);
346
Pratik Patelbfd2de62013-01-26 12:14:59 -0800347 /* Disable CSR configuration */
Pratik Patelb46038f2012-07-22 23:09:11 -0700348 msm_qdss_csr_disable_bam_to_usb();
349 drvdata->enable_to_bam = false;
350}
351
352static void tmc_etr_bam_disable(struct tmc_drvdata *drvdata)
353{
354 struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
355
356 if (!bamdata->enable)
357 return;
358
359 sps_disconnect(bamdata->pipe);
360 sps_free_endpoint(bamdata->pipe);
361 bamdata->enable = false;
362}
363
364static void usb_notifier(void *priv, unsigned int event,
365 struct qdss_request *d_req, struct usb_qdss_ch *ch)
366{
367 struct tmc_drvdata *drvdata = priv;
368 unsigned long flags;
369 int ret = 0;
370
371 mutex_lock(&drvdata->usb_lock);
372 if (event == USB_QDSS_CONNECT) {
373 tmc_etr_fill_usb_bam_data(drvdata);
374 ret = tmc_etr_bam_enable(drvdata);
375 if (ret)
376 dev_err(drvdata->dev, "ETR BAM enable failed\n");
377
378 spin_lock_irqsave(&drvdata->spinlock, flags);
379 __tmc_etr_enable_to_bam(drvdata);
380 spin_unlock_irqrestore(&drvdata->spinlock, flags);
381 } else if (event == USB_QDSS_DISCONNECT) {
382 spin_lock_irqsave(&drvdata->spinlock, flags);
383 __tmc_etr_disable_to_bam(drvdata);
384 spin_unlock_irqrestore(&drvdata->spinlock, flags);
385 tmc_etr_bam_disable(drvdata);
386 }
387 mutex_unlock(&drvdata->usb_lock);
388}
389
Pushkar Joshibf213a02013-05-03 13:18:44 -0700390static uint32_t tmc_etr_get_write_ptr(struct tmc_drvdata *drvdata)
391{
392 uint32_t rwp = 0;
393
394 TMC_UNLOCK(drvdata);
395
396 rwp = tmc_readl(drvdata, TMC_RWP);
397
398 TMC_LOCK(drvdata);
399
400 return rwp;
401}
402
403static void tmc_etr_byte_cntr_start(struct tmc_drvdata *drvdata)
404{
405 if (!drvdata->byte_cntr_present)
406 return;
407
408 mutex_lock(&drvdata->byte_cntr_lock);
409 atomic_set(&drvdata->byte_cntr_irq_cnt, 0);
410 drvdata->byte_cntr_overflow = false;
411 drvdata->byte_cntr_read_active = false;
412 drvdata->byte_cntr_enable = true;
413 if (drvdata->byte_cntr_value != 0)
414 drvdata->byte_cntr_overflow_cnt = drvdata->size /
415 (drvdata->byte_cntr_value * 8);
416 else
417 drvdata->byte_cntr_overflow_cnt = 0;
418 coresight_csr_set_byte_cntr(drvdata->byte_cntr_value);
419 mutex_unlock(&drvdata->byte_cntr_lock);
420}
421
422static void tmc_etr_byte_cntr_stop(struct tmc_drvdata *drvdata)
423{
424 if (!drvdata->byte_cntr_present)
425 return;
426
427 mutex_lock(&drvdata->byte_cntr_lock);
428 coresight_csr_set_byte_cntr(0);
429 drvdata->byte_cntr_value = 0;
430 drvdata->byte_cntr_enable = false;
431 mutex_unlock(&drvdata->byte_cntr_lock);
432
433 wake_up(&drvdata->wq);
434}
435
Pratik Patel22911492012-06-25 21:38:02 -0700436static void __tmc_etb_enable(struct tmc_drvdata *drvdata)
437{
438 /* Zero out the memory to help with debug */
439 memset(drvdata->buf, 0, drvdata->size);
440
441 TMC_UNLOCK(drvdata);
442
443 tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
Pratik Patel7c0b3722013-02-08 11:57:27 -0800444 tmc_writel(drvdata, 0x1133, TMC_FFCR);
Pratik Patel22911492012-06-25 21:38:02 -0700445 tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
446 __tmc_enable(drvdata);
447
448 TMC_LOCK(drvdata);
449}
450
Pratik Patelb46038f2012-07-22 23:09:11 -0700451static void __tmc_etr_enable_to_mem(struct tmc_drvdata *drvdata)
Pratik Patel22911492012-06-25 21:38:02 -0700452{
453 uint32_t axictl;
454
455 /* Zero out the memory to help with debug */
456 memset(drvdata->vaddr, 0, drvdata->size);
457
458 TMC_UNLOCK(drvdata);
459
460 tmc_writel(drvdata, drvdata->size / BYTES_PER_WORD, TMC_RSZ);
461 tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
462
463 axictl = tmc_readl(drvdata, TMC_AXICTL);
464 axictl |= (0xF << 8);
465 tmc_writel(drvdata, axictl, TMC_AXICTL);
466 axictl &= ~(0x1 << 7);
467 tmc_writel(drvdata, axictl, TMC_AXICTL);
468 axictl = (axictl & ~0x3) | 0x2;
469 tmc_writel(drvdata, axictl, TMC_AXICTL);
470
471 tmc_writel(drvdata, drvdata->paddr, TMC_DBALO);
472 tmc_writel(drvdata, 0x0, TMC_DBAHI);
Pratik Patela5544162013-02-08 11:57:27 -0800473 tmc_writel(drvdata, 0x1133, TMC_FFCR);
Pratik Patelb46038f2012-07-22 23:09:11 -0700474 tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
Pratik Patel22911492012-06-25 21:38:02 -0700475 __tmc_enable(drvdata);
476
477 TMC_LOCK(drvdata);
478}
479
480static void __tmc_etf_enable(struct tmc_drvdata *drvdata)
481{
482 TMC_UNLOCK(drvdata);
483
484 tmc_writel(drvdata, TMC_MODE_HARDWARE_FIFO, TMC_MODE);
485 tmc_writel(drvdata, 0x3, TMC_FFCR);
486 tmc_writel(drvdata, 0x0, TMC_BUFWM);
487 __tmc_enable(drvdata);
488
489 TMC_LOCK(drvdata);
490}
491
492static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
493{
494 int ret;
495 unsigned long flags;
496
497 ret = clk_prepare_enable(drvdata->clk);
498 if (ret)
499 return ret;
500
Pratik Patelb46038f2012-07-22 23:09:11 -0700501 mutex_lock(&drvdata->usb_lock);
Pratik Patel7c0b3722013-02-08 11:57:27 -0800502 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
503 coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
504 coresight_cti_map_trigin(drvdata->cti_reset, 0, 0);
505 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
Pushkar Joshibf213a02013-05-03 13:18:44 -0700506 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
507 tmc_etr_byte_cntr_start(drvdata);
508 if (!drvdata->reset_flush_race) {
509 coresight_cti_map_trigout(drvdata->cti_flush,
510 3, 0);
511 coresight_cti_map_trigin(drvdata->cti_reset,
512 2, 0);
513 }
Pratik Patela5544162013-02-08 11:57:27 -0800514 } else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
Pratik Patelb46038f2012-07-22 23:09:11 -0700515 drvdata->usbch = usb_qdss_open("qdss", drvdata,
516 usb_notifier);
517 if (IS_ERR(drvdata->usbch)) {
518 dev_err(drvdata->dev, "usb_qdss_open failed\n");
519 ret = PTR_ERR(drvdata->usbch);
520 goto err0;
521 }
522 }
Pratik Patel7c0b3722013-02-08 11:57:27 -0800523 } else {
524 if (mode == TMC_MODE_CIRCULAR_BUFFER) {
525 coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
526 coresight_cti_map_trigin(drvdata->cti_reset, 0, 0);
527 }
Pratik Patelb46038f2012-07-22 23:09:11 -0700528 }
529
Pratik Patel22911492012-06-25 21:38:02 -0700530 spin_lock_irqsave(&drvdata->spinlock, flags);
531 if (drvdata->reading) {
Pratik Patelb46038f2012-07-22 23:09:11 -0700532 ret = -EBUSY;
533 goto err1;
Pratik Patel22911492012-06-25 21:38:02 -0700534 }
535
536 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
537 __tmc_etb_enable(drvdata);
538 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
Pratik Patelb46038f2012-07-22 23:09:11 -0700539 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
540 __tmc_etr_enable_to_mem(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -0700541 } else {
542 if (mode == TMC_MODE_CIRCULAR_BUFFER)
543 __tmc_etb_enable(drvdata);
544 else
545 __tmc_etf_enable(drvdata);
546 }
547 drvdata->enable = true;
548 spin_unlock_irqrestore(&drvdata->spinlock, flags);
Pratik Patelb46038f2012-07-22 23:09:11 -0700549 mutex_unlock(&drvdata->usb_lock);
Pratik Patel22911492012-06-25 21:38:02 -0700550
551 dev_info(drvdata->dev, "TMC enabled\n");
552 return 0;
Pratik Patelb46038f2012-07-22 23:09:11 -0700553err1:
554 spin_unlock_irqrestore(&drvdata->spinlock, flags);
555 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
556 if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
557 usb_qdss_close(drvdata->usbch);
558err0:
559 mutex_unlock(&drvdata->usb_lock);
560 clk_disable_unprepare(drvdata->clk);
561 return ret;
Pratik Patel22911492012-06-25 21:38:02 -0700562}
563
564static int tmc_enable_sink(struct coresight_device *csdev)
565{
566 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
567
568 return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
569}
570
571static int tmc_enable_link(struct coresight_device *csdev, int inport,
572 int outport)
573{
574 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
575
576 return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
577}
578
Pratik Patel84750b22012-12-11 21:56:19 -0800579static void __tmc_reg_dump(struct tmc_drvdata *drvdata)
580{
581 char *reg_hdr;
582 uint32_t *reg_buf;
583
584 if (!drvdata->reg_buf || !drvdata->aborting)
585 return;
586
587 reg_hdr = drvdata->reg_buf - PAGE_SIZE;
588 reg_buf = (uint32_t *)drvdata->reg_buf;
589
590 reg_buf[1] = tmc_readl(drvdata, TMC_RSZ);
591 reg_buf[3] = tmc_readl(drvdata, TMC_STS);
592 reg_buf[5] = tmc_readl(drvdata, TMC_RRP);
593 reg_buf[6] = tmc_readl(drvdata, TMC_RWP);
594 reg_buf[7] = tmc_readl(drvdata, TMC_TRG);
595 reg_buf[8] = tmc_readl(drvdata, TMC_CTL);
596 reg_buf[10] = tmc_readl(drvdata, TMC_MODE);
597 reg_buf[11] = tmc_readl(drvdata, TMC_LBUFLEVEL);
598 reg_buf[12] = tmc_readl(drvdata, TMC_CBUFLEVEL);
599 reg_buf[13] = tmc_readl(drvdata, TMC_BUFWM);
600 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
601 reg_buf[14] = tmc_readl(drvdata, TMC_RRPHI);
602 reg_buf[15] = tmc_readl(drvdata, TMC_RWPHI);
603 reg_buf[68] = tmc_readl(drvdata, TMC_AXICTL);
604 reg_buf[70] = tmc_readl(drvdata, TMC_DBALO);
605 reg_buf[71] = tmc_readl(drvdata, TMC_DBAHI);
606 }
607 reg_buf[192] = tmc_readl(drvdata, TMC_FFSR);
608 reg_buf[193] = tmc_readl(drvdata, TMC_FFCR);
609 reg_buf[194] = tmc_readl(drvdata, TMC_PSCR);
610 reg_buf[1000] = tmc_readl(drvdata, CORESIGHT_CLAIMSET);
611 reg_buf[1001] = tmc_readl(drvdata, CORESIGHT_CLAIMCLR);
612 reg_buf[1005] = tmc_readl(drvdata, CORESIGHT_LSR);
613 reg_buf[1006] = tmc_readl(drvdata, CORESIGHT_AUTHSTATUS);
614 reg_buf[1010] = tmc_readl(drvdata, CORESIGHT_DEVID);
615 reg_buf[1011] = tmc_readl(drvdata, CORESIGHT_DEVTYPE);
616 reg_buf[1012] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR4);
617 reg_buf[1013] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR5);
618 reg_buf[1014] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR6);
619 reg_buf[1015] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR7);
620 reg_buf[1016] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR0);
621 reg_buf[1017] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR1);
622 reg_buf[1018] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR2);
623 reg_buf[1019] = tmc_readl(drvdata, CORESIGHT_PERIPHIDR3);
624 reg_buf[1020] = tmc_readl(drvdata, CORESIGHT_COMPIDR0);
625 reg_buf[1021] = tmc_readl(drvdata, CORESIGHT_COMPIDR1);
626 reg_buf[1022] = tmc_readl(drvdata, CORESIGHT_COMPIDR2);
627 reg_buf[1023] = tmc_readl(drvdata, CORESIGHT_COMPIDR3);
628
629 *(uint32_t *)(reg_hdr + TMC_REG_DUMP_MAGIC_OFF) = TMC_REG_DUMP_MAGIC;
630}
631
Pratik Patel22911492012-06-25 21:38:02 -0700632static void __tmc_etb_dump(struct tmc_drvdata *drvdata)
633{
634 enum tmc_mem_intf_width memwidth;
635 uint8_t memwords;
Pratik Patel84750b22012-12-11 21:56:19 -0800636 char *hdr;
Pratik Patel22911492012-06-25 21:38:02 -0700637 char *bufp;
638 uint32_t read_data;
639 int i;
640
641 memwidth = BMVAL(tmc_readl(drvdata, CORESIGHT_DEVID), 8, 10);
642 if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
643 memwords = 1;
644 else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
645 memwords = 2;
646 else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
647 memwords = 4;
648 else
649 memwords = 8;
650
651 bufp = drvdata->buf;
652 while (1) {
653 for (i = 0; i < memwords; i++) {
654 read_data = tmc_readl(drvdata, TMC_RRD);
655 if (read_data == 0xFFFFFFFF)
Pratik Patel84750b22012-12-11 21:56:19 -0800656 goto out;
Pratik Patel22911492012-06-25 21:38:02 -0700657 memcpy(bufp, &read_data, BYTES_PER_WORD);
658 bufp += BYTES_PER_WORD;
659 }
660 }
Pratik Patel84750b22012-12-11 21:56:19 -0800661
662out:
663 if (drvdata->aborting) {
664 hdr = drvdata->buf - PAGE_SIZE;
665 *(uint32_t *)(hdr + TMC_ETFETB_DUMP_MAGIC_OFF) =
666 TMC_ETFETB_DUMP_MAGIC;
667 }
Pratik Patel22911492012-06-25 21:38:02 -0700668}
669
670static void __tmc_etb_disable(struct tmc_drvdata *drvdata)
671{
672 TMC_UNLOCK(drvdata);
673
674 tmc_flush_and_stop(drvdata);
675 __tmc_etb_dump(drvdata);
Pratik Patel84750b22012-12-11 21:56:19 -0800676 __tmc_reg_dump(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -0700677 __tmc_disable(drvdata);
678
679 TMC_LOCK(drvdata);
680}
681
682static void __tmc_etr_dump(struct tmc_drvdata *drvdata)
683{
684 uint32_t rwp, rwphi;
685
686 rwp = tmc_readl(drvdata, TMC_RWP);
687 rwphi = tmc_readl(drvdata, TMC_RWPHI);
688
689 if (BVAL(tmc_readl(drvdata, TMC_STS), 0))
Pratik Patel05fe91e2012-08-10 10:47:08 -0700690 drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
Pratik Patel22911492012-06-25 21:38:02 -0700691 else
692 drvdata->buf = drvdata->vaddr;
693}
694
Pratik Patelb46038f2012-07-22 23:09:11 -0700695static void __tmc_etr_disable_to_mem(struct tmc_drvdata *drvdata)
Pratik Patel22911492012-06-25 21:38:02 -0700696{
697 TMC_UNLOCK(drvdata);
698
699 tmc_flush_and_stop(drvdata);
700 __tmc_etr_dump(drvdata);
Pratik Patel84750b22012-12-11 21:56:19 -0800701 __tmc_reg_dump(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -0700702 __tmc_disable(drvdata);
703
704 TMC_LOCK(drvdata);
705}
706
707static void __tmc_etf_disable(struct tmc_drvdata *drvdata)
708{
709 TMC_UNLOCK(drvdata);
710
711 tmc_flush_and_stop(drvdata);
712 __tmc_disable(drvdata);
713
714 TMC_LOCK(drvdata);
715}
716
717static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
718{
719 unsigned long flags;
720
Pratik Patelb46038f2012-07-22 23:09:11 -0700721 mutex_lock(&drvdata->usb_lock);
Pratik Patel22911492012-06-25 21:38:02 -0700722 spin_lock_irqsave(&drvdata->spinlock, flags);
723 if (drvdata->reading)
724 goto out;
725
726 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
727 __tmc_etb_disable(drvdata);
728 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
Pratik Patelb46038f2012-07-22 23:09:11 -0700729 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
730 __tmc_etr_disable_to_mem(drvdata);
731 else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
Pratik Patel7c0b3722013-02-08 11:57:27 -0800732 __tmc_etr_disable_to_bam(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -0700733 } else {
734 if (mode == TMC_MODE_CIRCULAR_BUFFER)
735 __tmc_etb_disable(drvdata);
736 else
737 __tmc_etf_disable(drvdata);
738 }
Pratik Patel22911492012-06-25 21:38:02 -0700739 drvdata->enable = false;
740 spin_unlock_irqrestore(&drvdata->spinlock, flags);
741
Pratik Patel7c0b3722013-02-08 11:57:27 -0800742 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
743 coresight_cti_unmap_trigin(drvdata->cti_reset, 0, 0);
744 coresight_cti_unmap_trigout(drvdata->cti_flush, 1, 0);
745 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
Pushkar Joshibf213a02013-05-03 13:18:44 -0700746 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
747 tmc_etr_byte_cntr_stop(drvdata);
748 if (!drvdata->reset_flush_race) {
749 coresight_cti_unmap_trigin(drvdata->cti_reset,
750 2, 0);
751 coresight_cti_unmap_trigout(drvdata->cti_flush,
752 3, 0);
753 }
Pratik Patela5544162013-02-08 11:57:27 -0800754 } else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB) {
Pratik Patel7c0b3722013-02-08 11:57:27 -0800755 tmc_etr_bam_disable(drvdata);
756 usb_qdss_close(drvdata->usbch);
757 }
758 } else {
759 if (mode == TMC_MODE_CIRCULAR_BUFFER) {
760 coresight_cti_unmap_trigin(drvdata->cti_reset, 0, 0);
761 coresight_cti_unmap_trigout(drvdata->cti_flush, 1, 0);
Pratik Patelb46038f2012-07-22 23:09:11 -0700762 }
763 }
764 mutex_unlock(&drvdata->usb_lock);
765
Pratik Patel22911492012-06-25 21:38:02 -0700766 clk_disable_unprepare(drvdata->clk);
767
768 dev_info(drvdata->dev, "TMC disabled\n");
Pratik Patel7c0b3722013-02-08 11:57:27 -0800769 return;
770out:
771 drvdata->enable = false;
772 spin_unlock_irqrestore(&drvdata->spinlock, flags);
773 mutex_unlock(&drvdata->usb_lock);
774
775 clk_disable_unprepare(drvdata->clk);
776
777 dev_info(drvdata->dev, "TMC disabled\n");
Pratik Patel22911492012-06-25 21:38:02 -0700778}
779
780static void tmc_disable_sink(struct coresight_device *csdev)
781{
782 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
783
784 tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
785}
786
787static void tmc_disable_link(struct coresight_device *csdev, int inport,
788 int outport)
789{
790 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
791
792 tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
793}
794
Pratik Patelcf7d0452012-07-02 13:57:20 -0700795static void tmc_abort(struct coresight_device *csdev)
796{
797 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
798 unsigned long flags;
799 enum tmc_mode mode;
800
Pratik Patel84750b22012-12-11 21:56:19 -0800801 drvdata->aborting = true;
802
Pratik Patelcf7d0452012-07-02 13:57:20 -0700803 spin_lock_irqsave(&drvdata->spinlock, flags);
804 if (drvdata->reading)
805 goto out0;
806
807 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
808 __tmc_etb_disable(drvdata);
809 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
Pratik Patelb46038f2012-07-22 23:09:11 -0700810 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
811 __tmc_etr_disable_to_mem(drvdata);
Pratik Patel89a76622013-02-09 21:34:41 -0800812 else if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
813 __tmc_etr_disable_to_bam(drvdata);
Pratik Patelcf7d0452012-07-02 13:57:20 -0700814 } else {
815 mode = tmc_readl(drvdata, TMC_MODE);
816 if (mode == TMC_MODE_CIRCULAR_BUFFER)
817 __tmc_etb_disable(drvdata);
818 else
819 goto out1;
820 }
821out0:
822 drvdata->enable = false;
823 spin_unlock_irqrestore(&drvdata->spinlock, flags);
824
825 dev_info(drvdata->dev, "TMC aborted\n");
826 return;
827out1:
828 spin_unlock_irqrestore(&drvdata->spinlock, flags);
829}
830
Pratik Patel22911492012-06-25 21:38:02 -0700831static const struct coresight_ops_sink tmc_sink_ops = {
832 .enable = tmc_enable_sink,
833 .disable = tmc_disable_sink,
Pratik Patelcf7d0452012-07-02 13:57:20 -0700834 .abort = tmc_abort,
Pratik Patel22911492012-06-25 21:38:02 -0700835};
836
837static const struct coresight_ops_link tmc_link_ops = {
838 .enable = tmc_enable_link,
839 .disable = tmc_disable_link,
840};
841
842static const struct coresight_ops tmc_etb_cs_ops = {
843 .sink_ops = &tmc_sink_ops,
844};
845
846static const struct coresight_ops tmc_etr_cs_ops = {
847 .sink_ops = &tmc_sink_ops,
848};
849
850static const struct coresight_ops tmc_etf_cs_ops = {
851 .sink_ops = &tmc_sink_ops,
852 .link_ops = &tmc_link_ops,
853};
854
855static int tmc_read_prepare(struct tmc_drvdata *drvdata)
856{
857 int ret;
858 unsigned long flags;
859 enum tmc_mode mode;
860
861 spin_lock_irqsave(&drvdata->spinlock, flags);
862 if (!drvdata->enable)
863 goto out;
864
865 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
866 __tmc_etb_disable(drvdata);
867 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
Pratik Patelb46038f2012-07-22 23:09:11 -0700868 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
869 __tmc_etr_disable_to_mem(drvdata);
870 } else {
871 ret = -ENODEV;
872 goto err;
873 }
Pratik Patel22911492012-06-25 21:38:02 -0700874 } else {
875 mode = tmc_readl(drvdata, TMC_MODE);
876 if (mode == TMC_MODE_CIRCULAR_BUFFER) {
877 __tmc_etb_disable(drvdata);
878 } else {
879 ret = -ENODEV;
880 goto err;
881 }
882 }
883out:
884 drvdata->reading = true;
885 spin_unlock_irqrestore(&drvdata->spinlock, flags);
886
887 dev_info(drvdata->dev, "TMC read start\n");
888 return 0;
889err:
890 spin_unlock_irqrestore(&drvdata->spinlock, flags);
891 return ret;
892}
893
894static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
895{
896 unsigned long flags;
897 enum tmc_mode mode;
898
899 spin_lock_irqsave(&drvdata->spinlock, flags);
900 if (!drvdata->enable)
901 goto out;
902
903 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
904 __tmc_etb_enable(drvdata);
905 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
Pratik Patelb46038f2012-07-22 23:09:11 -0700906 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
907 __tmc_etr_enable_to_mem(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -0700908 } else {
909 mode = tmc_readl(drvdata, TMC_MODE);
910 if (mode == TMC_MODE_CIRCULAR_BUFFER)
911 __tmc_etb_enable(drvdata);
912 }
913out:
914 drvdata->reading = false;
915 spin_unlock_irqrestore(&drvdata->spinlock, flags);
916
917 dev_info(drvdata->dev, "TMC read end\n");
918}
919
920static int tmc_open(struct inode *inode, struct file *file)
921{
922 struct tmc_drvdata *drvdata = container_of(file->private_data,
923 struct tmc_drvdata, miscdev);
924 int ret = 0;
925
Pratik Patelb46038f2012-07-22 23:09:11 -0700926 mutex_lock(&drvdata->read_lock);
Pratik Patel22911492012-06-25 21:38:02 -0700927 if (drvdata->read_count++)
928 goto out;
929
930 ret = tmc_read_prepare(drvdata);
931 if (ret)
Pratik Patelb46038f2012-07-22 23:09:11 -0700932 goto err;
Pratik Patel22911492012-06-25 21:38:02 -0700933out:
Pratik Patelb46038f2012-07-22 23:09:11 -0700934 mutex_unlock(&drvdata->read_lock);
Pratik Patel22911492012-06-25 21:38:02 -0700935 nonseekable_open(inode, file);
936
937 dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
938 return 0;
Pratik Patelb46038f2012-07-22 23:09:11 -0700939err:
940 drvdata->read_count--;
941 mutex_unlock(&drvdata->read_lock);
942 return ret;
Pratik Patel22911492012-06-25 21:38:02 -0700943}
944
945static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
946 loff_t *ppos)
947{
948 struct tmc_drvdata *drvdata = container_of(file->private_data,
949 struct tmc_drvdata, miscdev);
950 char *bufp = drvdata->buf + *ppos;
951
952 if (*ppos + len > drvdata->size)
953 len = drvdata->size - *ppos;
954
955 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
956 if (bufp == (char *)(drvdata->vaddr + drvdata->size))
957 bufp = drvdata->vaddr;
Pratik Patel05fe91e2012-08-10 10:47:08 -0700958 else if (bufp > (char *)(drvdata->vaddr + drvdata->size))
959 bufp -= drvdata->size;
Pratik Patel22911492012-06-25 21:38:02 -0700960 if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
961 len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
962 }
963
964 if (copy_to_user(data, bufp, len)) {
965 dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
966 return -EFAULT;
967 }
968
969 *ppos += len;
970
971 dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
972 __func__, len, (int) (drvdata->size - *ppos));
973 return len;
974}
975
976static int tmc_release(struct inode *inode, struct file *file)
977{
978 struct tmc_drvdata *drvdata = container_of(file->private_data,
979 struct tmc_drvdata, miscdev);
980
Pratik Patelb46038f2012-07-22 23:09:11 -0700981 mutex_lock(&drvdata->read_lock);
Pratik Patel22911492012-06-25 21:38:02 -0700982 if (--drvdata->read_count) {
983 if (drvdata->read_count < 0) {
984 WARN_ONCE(1, "mismatched close\n");
985 drvdata->read_count = 0;
986 }
987 goto out;
988 }
989
990 tmc_read_unprepare(drvdata);
991out:
Pratik Patelb46038f2012-07-22 23:09:11 -0700992 mutex_unlock(&drvdata->read_lock);
Pratik Patel22911492012-06-25 21:38:02 -0700993 dev_dbg(drvdata->dev, "%s: released\n", __func__);
994 return 0;
995}
996
997static const struct file_operations tmc_fops = {
998 .owner = THIS_MODULE,
999 .open = tmc_open,
1000 .read = tmc_read,
1001 .release = tmc_release,
1002 .llseek = no_llseek,
1003};
1004
Pushkar Joshibf213a02013-05-03 13:18:44 -07001005static int tmc_etr_byte_cntr_open(struct inode *inode, struct file *file)
1006{
1007 struct tmc_drvdata *drvdata = container_of(inode->i_cdev,
1008 struct tmc_drvdata,
1009 byte_cntr_dev);
1010
1011 if (drvdata->out_mode != TMC_ETR_OUT_MODE_MEM ||
1012 !drvdata->byte_cntr_enable)
1013 return -EPERM;
1014
1015 if (!mutex_trylock(&drvdata->byte_cntr_read_lock))
1016 return -EPERM;
1017
1018 file->private_data = drvdata;
1019 nonseekable_open(inode, file);
1020 drvdata->byte_cntr_block_size = drvdata->byte_cntr_value * 8;
1021 drvdata->byte_cntr_read_active = true;
1022 dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
1023 return 0;
1024}
1025
1026static void tmc_etr_read_bytes(struct tmc_drvdata *drvdata, loff_t *ppos,
1027 size_t bytes, size_t *len)
1028{
1029 if (*len >= bytes) {
1030 atomic_dec(&drvdata->byte_cntr_irq_cnt);
1031 *len = bytes;
1032 } else {
1033 if (((uint32_t)*ppos % bytes) + *len > bytes)
1034 *len = bytes - ((uint32_t)*ppos % bytes);
1035 if ((*len + (uint32_t)*ppos) % bytes == 0)
1036 atomic_dec(&drvdata->byte_cntr_irq_cnt);
1037 }
1038}
1039
1040static size_t tmc_etr_flush_bytes(struct tmc_drvdata *drvdata, loff_t *ppos,
1041 size_t bytes)
1042{
1043 uint32_t rwp = 0;
1044 size_t len = bytes;
1045
1046 rwp = tmc_etr_get_write_ptr(drvdata);
1047 if (rwp >= (drvdata->paddr + *ppos)) {
1048 if (len > (rwp - drvdata->paddr - *ppos))
1049 len = rwp - drvdata->paddr - *ppos;
1050 }
1051 return len;
1052}
1053
1054static ssize_t tmc_etr_byte_cntr_read(struct file *file, char __user *data,
1055 size_t len, loff_t *ppos)
1056{
1057 struct tmc_drvdata *drvdata = file->private_data;
1058 char *bufp = drvdata->vaddr + *ppos;
1059 size_t bytes = drvdata->byte_cntr_block_size;
1060 int ret = 0;
1061
1062 if (!data)
1063 return -EINVAL;
1064 if (drvdata->byte_cntr_overflow)
1065 return -EIO;
1066
1067 mutex_lock(&drvdata->byte_cntr_lock);
1068 /* In case the byte counter is enabled and disabled multiple times
1069 * prevent unexpected data from being given to the user
1070 */
1071 if (!drvdata->byte_cntr_read_active)
1072 goto read_err0;
1073
1074 if (!drvdata->byte_cntr_enable) {
1075 if (!atomic_read(&drvdata->byte_cntr_irq_cnt)) {
1076 /* Read the last 'block' of data which might be needed
1077 * to be read partially. If already read, return 0
1078 */
1079 len = tmc_etr_flush_bytes(drvdata, ppos, bytes);
1080 if (!len)
1081 goto read_err0;
1082 } else {
1083 /* Keep reading until you reach the last block of data
1084 */
1085 tmc_etr_read_bytes(drvdata, ppos, bytes, &len);
1086 }
1087 } else {
1088 if (!atomic_read(&drvdata->byte_cntr_irq_cnt)) {
1089 mutex_unlock(&drvdata->byte_cntr_lock);
1090 if (wait_event_interruptible(drvdata->wq,
1091 (atomic_read(&drvdata->byte_cntr_irq_cnt) > 0) ||
1092 !drvdata->byte_cntr_enable)) {
1093 ret = -ERESTARTSYS;
1094 goto read_err1;
1095 }
1096 mutex_lock(&drvdata->byte_cntr_lock);
1097 if (!drvdata->byte_cntr_read_active) {
1098 ret = 0;
1099 goto read_err0;
1100 }
1101 }
1102 if (drvdata->byte_cntr_overflow) {
1103 ret = -EIO;
1104 goto read_err0;
1105 }
1106 if (!drvdata->byte_cntr_enable &&
1107 !atomic_read(&drvdata->byte_cntr_irq_cnt)) {
1108 len = tmc_etr_flush_bytes(drvdata, ppos, bytes);
1109 if (!len) {
1110 ret = 0;
1111 goto read_err0;
1112 }
1113 } else {
1114 tmc_etr_read_bytes(drvdata, ppos, bytes, &len);
1115 }
1116 }
1117 if (copy_to_user(data, bufp, len)) {
1118 mutex_unlock(&drvdata->byte_cntr_lock);
1119 dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
1120 ret = -EFAULT;
1121 goto read_err1;
1122 }
1123 mutex_unlock(&drvdata->byte_cntr_lock);
1124
1125 if (*ppos + len >= drvdata->size)
1126 *ppos = 0;
1127 else
1128 *ppos += len;
1129
1130 dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
1131 __func__, len, (int) (drvdata->size - *ppos));
1132 return len;
1133
1134read_err0:
1135 mutex_unlock(&drvdata->byte_cntr_lock);
1136read_err1:
1137 return ret;
1138}
1139
1140static int tmc_etr_byte_cntr_release(struct inode *inode, struct file *file)
1141{
1142 struct tmc_drvdata *drvdata = file->private_data;
1143
1144 mutex_lock(&drvdata->byte_cntr_lock);
1145 drvdata->byte_cntr_read_active = false;
1146 mutex_unlock(&drvdata->byte_cntr_lock);
1147 mutex_unlock(&drvdata->byte_cntr_read_lock);
1148 dev_dbg(drvdata->dev, "%s: released\n", __func__);
1149 return 0;
1150}
1151
1152static const struct file_operations byte_cntr_fops = {
1153 .owner = THIS_MODULE,
1154 .open = tmc_etr_byte_cntr_open,
1155 .read = tmc_etr_byte_cntr_read,
1156 .release = tmc_etr_byte_cntr_release,
1157 .llseek = no_llseek,
1158};
1159
Pratik Patel22911492012-06-25 21:38:02 -07001160static ssize_t tmc_show_trigger_cntr(struct device *dev,
1161 struct device_attribute *attr, char *buf)
1162{
1163 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
1164 unsigned long val = drvdata->trigger_cntr;
1165
1166 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1167}
1168
1169static ssize_t tmc_store_trigger_cntr(struct device *dev,
1170 struct device_attribute *attr,
1171 const char *buf, size_t size)
1172{
1173 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
1174 unsigned long val;
1175
1176 if (sscanf(buf, "%lx", &val) != 1)
1177 return -EINVAL;
1178
1179 drvdata->trigger_cntr = val;
1180 return size;
1181}
1182static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, tmc_show_trigger_cntr,
1183 tmc_store_trigger_cntr);
1184
Pratik Patelb46038f2012-07-22 23:09:11 -07001185static ssize_t tmc_etr_show_out_mode(struct device *dev,
1186 struct device_attribute *attr, char *buf)
1187{
1188 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
1189
1190 return scnprintf(buf, PAGE_SIZE, "%s\n",
1191 drvdata->out_mode == TMC_ETR_OUT_MODE_MEM ?
1192 "mem" : "usb");
1193}
1194
1195static ssize_t tmc_etr_store_out_mode(struct device *dev,
1196 struct device_attribute *attr,
1197 const char *buf, size_t size)
1198{
1199 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
1200 char str[10] = "";
1201 unsigned long flags;
Pratik Patelb46038f2012-07-22 23:09:11 -07001202 int ret;
1203
1204 if (strlen(buf) >= 10)
1205 return -EINVAL;
1206 if (sscanf(buf, "%s", str) != 1)
1207 return -EINVAL;
1208
1209 mutex_lock(&drvdata->usb_lock);
1210 if (!strcmp(str, "mem")) {
1211 if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
1212 goto out;
1213
1214 spin_lock_irqsave(&drvdata->spinlock, flags);
Pratik Patela5544162013-02-08 11:57:27 -08001215 if (!drvdata->enable) {
1216 drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
1217 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1218 goto out;
Pratik Patelb46038f2012-07-22 23:09:11 -07001219 }
Pratik Patela5544162013-02-08 11:57:27 -08001220 __tmc_etr_disable_to_bam(drvdata);
1221 __tmc_etr_enable_to_mem(drvdata);
Pratik Patelb46038f2012-07-22 23:09:11 -07001222 drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
1223 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1224
Pratik Patela5544162013-02-08 11:57:27 -08001225 if (!drvdata->reset_flush_race) {
1226 coresight_cti_map_trigout(drvdata->cti_flush, 3, 0);
Pratik Pateld96ae502013-05-20 14:47:27 -07001227 coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
Pratik Patelb46038f2012-07-22 23:09:11 -07001228 }
Pratik Patela5544162013-02-08 11:57:27 -08001229
1230 tmc_etr_bam_disable(drvdata);
1231 usb_qdss_close(drvdata->usbch);
Pratik Patelb46038f2012-07-22 23:09:11 -07001232 } else if (!strcmp(str, "usb")) {
1233 if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
1234 goto out;
1235
1236 spin_lock_irqsave(&drvdata->spinlock, flags);
Pratik Patela5544162013-02-08 11:57:27 -08001237 if (!drvdata->enable) {
1238 drvdata->out_mode = TMC_ETR_OUT_MODE_USB;
1239 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1240 goto out;
Pratik Patelb46038f2012-07-22 23:09:11 -07001241 }
Pratik Patela5544162013-02-08 11:57:27 -08001242 if (drvdata->reading) {
1243 ret = -EBUSY;
1244 goto err1;
1245 }
1246 __tmc_etr_disable_to_mem(drvdata);
Pratik Patelb46038f2012-07-22 23:09:11 -07001247 drvdata->out_mode = TMC_ETR_OUT_MODE_USB;
1248 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1249
Pratik Patela5544162013-02-08 11:57:27 -08001250 if (!drvdata->reset_flush_race) {
Pratik Pateld96ae502013-05-20 14:47:27 -07001251 coresight_cti_unmap_trigin(drvdata->cti_reset, 2, 0);
Pratik Patela5544162013-02-08 11:57:27 -08001252 coresight_cti_unmap_trigout(drvdata->cti_flush, 3, 0);
1253 }
1254
1255 drvdata->usbch = usb_qdss_open("qdss", drvdata,
1256 usb_notifier);
1257 if (IS_ERR(drvdata->usbch)) {
1258 dev_err(drvdata->dev, "usb_qdss_open failed\n");
1259 ret = PTR_ERR(drvdata->usbch);
1260 goto err0;
Pratik Patelb46038f2012-07-22 23:09:11 -07001261 }
1262 }
1263out:
1264 mutex_unlock(&drvdata->usb_lock);
1265 return size;
1266err1:
1267 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1268err0:
1269 mutex_unlock(&drvdata->usb_lock);
1270 return ret;
1271}
1272static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tmc_etr_show_out_mode,
1273 tmc_etr_store_out_mode);
1274
Pushkar Joshibf213a02013-05-03 13:18:44 -07001275static ssize_t tmc_etr_show_byte_cntr_value(struct device *dev,
1276 struct device_attribute *attr,
1277 char *buf)
1278{
1279 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
1280 unsigned long val = drvdata->byte_cntr_value;
1281
1282 if (!drvdata->byte_cntr_present)
1283 return -EPERM;
1284
1285 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1286}
1287
1288static ssize_t tmc_etr_store_byte_cntr_value(struct device *dev,
1289 struct device_attribute *attr,
1290 const char *buf, size_t size)
1291{
1292 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
1293 unsigned long val;
1294
1295 if (!drvdata->byte_cntr_present || drvdata->byte_cntr_enable)
1296 return -EPERM;
1297 if (sscanf(buf, "%lx", &val) != 1)
1298 return -EINVAL;
1299 if ((drvdata->size / 8) < val)
1300 return -EINVAL;
1301 if (drvdata->size % (val * 8) != 0)
1302 return -EINVAL;
1303
1304 drvdata->byte_cntr_value = val;
1305 return size;
1306}
1307static DEVICE_ATTR(byte_cntr_value, S_IRUGO | S_IWUSR,
1308 tmc_etr_show_byte_cntr_value, tmc_etr_store_byte_cntr_value);
1309
Pratik Patel22911492012-06-25 21:38:02 -07001310static struct attribute *tmc_attrs[] = {
1311 &dev_attr_trigger_cntr.attr,
1312 NULL,
1313};
1314
1315static struct attribute_group tmc_attr_grp = {
1316 .attrs = tmc_attrs,
1317};
1318
Pratik Patelb46038f2012-07-22 23:09:11 -07001319static struct attribute *tmc_etr_attrs[] = {
1320 &dev_attr_out_mode.attr,
Pushkar Joshibf213a02013-05-03 13:18:44 -07001321 &dev_attr_byte_cntr_value.attr,
Pratik Patelb46038f2012-07-22 23:09:11 -07001322 NULL,
1323};
1324
1325static struct attribute_group tmc_etr_attr_grp = {
1326 .attrs = tmc_etr_attrs,
1327};
1328
Pratik Patel22911492012-06-25 21:38:02 -07001329static const struct attribute_group *tmc_etb_attr_grps[] = {
1330 &tmc_attr_grp,
1331 NULL,
1332};
1333
1334static const struct attribute_group *tmc_etr_attr_grps[] = {
1335 &tmc_attr_grp,
Pratik Patelb46038f2012-07-22 23:09:11 -07001336 &tmc_etr_attr_grp,
Pratik Patel22911492012-06-25 21:38:02 -07001337 NULL,
1338};
1339
1340static const struct attribute_group *tmc_etf_attr_grps[] = {
1341 &tmc_attr_grp,
1342 NULL,
1343};
1344
Pratik Patelb46038f2012-07-22 23:09:11 -07001345static int __devinit tmc_etr_bam_init(struct platform_device *pdev,
1346 struct tmc_drvdata *drvdata)
1347{
1348 struct device *dev = &pdev->dev;
1349 struct resource *res;
1350 struct tmc_etr_bam_data *bamdata;
1351
1352 bamdata = devm_kzalloc(dev, sizeof(*bamdata), GFP_KERNEL);
1353 if (!bamdata)
1354 return -ENOMEM;
1355 drvdata->bamdata = bamdata;
1356
Aparna Dasc9907512013-03-08 10:20:52 -08001357 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bam-base");
Pratik Patelb46038f2012-07-22 23:09:11 -07001358 if (!res)
1359 return -ENODEV;
1360
1361 bamdata->props.phys_addr = res->start;
1362 bamdata->props.virt_addr = devm_ioremap(dev, res->start,
1363 resource_size(res));
1364 if (!bamdata->props.virt_addr)
1365 return -ENOMEM;
1366 bamdata->props.virt_size = resource_size(res);
1367
1368 bamdata->props.event_threshold = 0x4; /* Pipe event threshold */
1369 bamdata->props.summing_threshold = 0x10; /* BAM event threshold */
1370 bamdata->props.irq = 0;
1371 bamdata->props.num_pipes = TMC_ETR_BAM_NR_PIPES;
1372
1373 return sps_register_bam_device(&bamdata->props, &bamdata->handle);
1374}
1375
1376static void tmc_etr_bam_exit(struct tmc_drvdata *drvdata)
1377{
1378 struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
1379
1380 if (!bamdata->handle)
1381 return;
1382 sps_deregister_bam_device(bamdata->handle);
1383}
1384
Pushkar Joshibf213a02013-05-03 13:18:44 -07001385static irqreturn_t tmc_etr_byte_cntr_irq(int irq, void *data)
1386{
1387 struct tmc_drvdata *drvdata = data;
1388
1389 atomic_inc(&drvdata->byte_cntr_irq_cnt);
1390 if (atomic_read(&drvdata->byte_cntr_irq_cnt) >
1391 drvdata->byte_cntr_overflow_cnt) {
1392 dev_err(drvdata->dev, "Byte counter overflow\n");
1393 drvdata->byte_cntr_overflow = true;
1394 }
1395 wake_up(&drvdata->wq);
1396 return IRQ_HANDLED;
1397}
1398
1399static int tmc_etr_byte_cntr_dev_register(struct tmc_drvdata *drvdata)
1400{
1401 int ret;
1402 struct device *device;
1403 dev_t dev;
1404
1405 ret = alloc_chrdev_region(&dev, 0, 1, drvdata->byte_cntr_node);
1406 if (ret)
1407 goto dev_err0;
1408 cdev_init(&drvdata->byte_cntr_dev, &byte_cntr_fops);
1409 drvdata->byte_cntr_dev.owner = THIS_MODULE;
1410 drvdata->byte_cntr_dev.ops = &byte_cntr_fops;
1411 ret = cdev_add(&drvdata->byte_cntr_dev, dev, 1);
1412 if (ret)
1413 goto dev_err1;
1414 drvdata->byte_cntr_class = class_create(THIS_MODULE,
1415 drvdata->byte_cntr_node);
1416 if (!drvdata->byte_cntr_class)
1417 goto dev_err2;
1418 device = device_create(drvdata->byte_cntr_class, NULL,
1419 drvdata->byte_cntr_dev.dev, drvdata,
1420 drvdata->byte_cntr_node);
1421 if (IS_ERR(device)) {
1422 ret = PTR_ERR(device);
1423 goto dev_err3;
1424 }
1425 return 0;
1426dev_err3:
1427 class_destroy(drvdata->byte_cntr_class);
1428dev_err2:
1429 cdev_del(&drvdata->byte_cntr_dev);
1430dev_err1:
1431 unregister_chrdev_region(drvdata->byte_cntr_dev.dev, 1);
1432dev_err0:
1433 return ret;
1434}
1435
1436static void tmc_etr_byte_cntr_dev_deregister(struct tmc_drvdata *drvdata)
1437{
1438 device_destroy(drvdata->byte_cntr_class, drvdata->byte_cntr_dev.dev);
1439 class_destroy(drvdata->byte_cntr_class);
1440 cdev_del(&drvdata->byte_cntr_dev);
1441 unregister_chrdev_region(drvdata->byte_cntr_dev.dev, 1);
1442}
1443
1444static int tmc_etr_byte_cntr_init(struct platform_device *pdev,
1445 struct tmc_drvdata *drvdata)
1446{
1447 int ret = 0;
1448 size_t node_size = strlen("-stream") + 1;
1449 char *node_name = (char *)((struct coresight_platform_data *)
1450 (pdev->dev.platform_data))->name;
1451
1452 if (!drvdata->byte_cntr_present) {
1453 dev_info(&pdev->dev, "Byte Counter feature absent\n");
1454 return 0;
1455 }
1456
1457 drvdata->byte_cntr_irq = platform_get_irq_byname(pdev,
1458 "byte-cntr-irq");
1459 if (drvdata->byte_cntr_irq < 0) {
1460 dev_err(&pdev->dev, "Byte-cntr-irq not specified\n");
1461 return 0;
1462 }
1463 ret = devm_request_irq(&pdev->dev, drvdata->byte_cntr_irq,
1464 tmc_etr_byte_cntr_irq,
1465 IRQF_TRIGGER_RISING | IRQF_SHARED,
1466 node_name, drvdata);
1467 if (ret) {
1468 dev_err(&pdev->dev, "Request irq failed\n");
1469 return ret;
1470 }
1471 init_waitqueue_head(&drvdata->wq);
1472 node_size += strlen(node_name);
1473 drvdata->byte_cntr_node = devm_kzalloc(&pdev->dev,
1474 node_size, GFP_KERNEL);
1475 strlcpy(drvdata->byte_cntr_node, node_name, node_size);
1476 strlcat(drvdata->byte_cntr_node, "-stream", node_size);
1477 ret = tmc_etr_byte_cntr_dev_register(drvdata);
1478 if (ret) {
1479 dev_err(&pdev->dev, "Byte cntr node not registered\n");
1480 return ret;
1481 }
1482 dev_info(&pdev->dev, "Byte Counter feature enabled\n");
1483 return 0;
1484}
1485
1486static void tmc_etr_byte_cntr_exit(struct tmc_drvdata *drvdata)
1487{
1488 if (drvdata->byte_cntr_present)
1489 tmc_etr_byte_cntr_dev_deregister(drvdata);
1490}
1491
Pratik Patel22911492012-06-25 21:38:02 -07001492static int __devinit tmc_probe(struct platform_device *pdev)
1493{
1494 int ret;
1495 uint32_t devid;
1496 struct device *dev = &pdev->dev;
1497 struct coresight_platform_data *pdata;
1498 struct tmc_drvdata *drvdata;
1499 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07001500 uint32_t reg_size;
1501 static int etfetb_count;
1502 static int count;
1503 void *baddr;
1504 struct msm_client_dump dump;
Pratik Patel7c0b3722013-02-08 11:57:27 -08001505 struct coresight_cti_data *ctidata;
Pratik Patel22911492012-06-25 21:38:02 -07001506 struct coresight_desc *desc;
1507
Pratik Patel49306402013-06-14 01:02:08 -07001508 if (coresight_fuse_access_disabled())
1509 return -EPERM;
1510
Pratik Patel22911492012-06-25 21:38:02 -07001511 if (pdev->dev.of_node) {
1512 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1513 if (IS_ERR(pdata))
1514 return PTR_ERR(pdata);
1515 pdev->dev.platform_data = pdata;
1516 }
1517
1518 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1519 if (!drvdata)
1520 return -ENOMEM;
1521 drvdata->dev = &pdev->dev;
1522 platform_set_drvdata(pdev, drvdata);
1523
Aparna Dasc9907512013-03-08 10:20:52 -08001524 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tmc-base");
Pratik Patel22911492012-06-25 21:38:02 -07001525 if (!res)
1526 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07001527 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07001528
Pratik Patel22911492012-06-25 21:38:02 -07001529 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1530 if (!drvdata->base)
1531 return -ENOMEM;
1532
1533 spin_lock_init(&drvdata->spinlock);
Pratik Patelb46038f2012-07-22 23:09:11 -07001534 mutex_init(&drvdata->read_lock);
1535 mutex_init(&drvdata->usb_lock);
Pushkar Joshibf213a02013-05-03 13:18:44 -07001536 mutex_init(&drvdata->byte_cntr_lock);
1537 mutex_init(&drvdata->byte_cntr_read_lock);
1538 atomic_set(&drvdata->byte_cntr_irq_cnt, 0);
Pratik Patel22911492012-06-25 21:38:02 -07001539
1540 drvdata->clk = devm_clk_get(dev, "core_clk");
1541 if (IS_ERR(drvdata->clk))
1542 return PTR_ERR(drvdata->clk);
Pratik Patel2c09b762012-07-21 15:54:54 -07001543
Pratik Patel22911492012-06-25 21:38:02 -07001544 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
1545 if (ret)
1546 return ret;
1547
1548 ret = clk_prepare_enable(drvdata->clk);
1549 if (ret)
1550 return ret;
Pratik Patel2c09b762012-07-21 15:54:54 -07001551
Pratik Patel22911492012-06-25 21:38:02 -07001552 devid = tmc_readl(drvdata, CORESIGHT_DEVID);
1553 drvdata->config_type = BMVAL(devid, 6, 7);
Pratik Patel2c09b762012-07-21 15:54:54 -07001554
Pratik Patel8c86adf2012-12-07 13:42:12 -08001555 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
1556 if (pdev->dev.of_node) {
1557 ret = of_property_read_u32(pdev->dev.of_node,
1558 "qcom,memory-reservation-size", &drvdata->size);
1559 if (ret) {
1560 clk_disable_unprepare(drvdata->clk);
1561 return ret;
1562 }
1563 }
1564 } else {
Pratik Patele411ac72012-10-31 16:38:05 -07001565 drvdata->size = tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD;
Pratik Patel8c86adf2012-12-07 13:42:12 -08001566 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001567
Pratik Patel22911492012-06-25 21:38:02 -07001568 clk_disable_unprepare(drvdata->clk);
1569
1570 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
1571 drvdata->paddr = allocate_contiguous_ebi_nomap(drvdata->size,
1572 SZ_4K);
1573 if (!drvdata->paddr)
1574 return -ENOMEM;
1575 drvdata->vaddr = devm_ioremap(dev, drvdata->paddr,
1576 drvdata->size);
1577 if (!drvdata->vaddr) {
1578 ret = -ENOMEM;
1579 goto err0;
1580 }
1581 memset(drvdata->vaddr, 0, drvdata->size);
Pratik Patelcd8ac7a2012-10-01 16:05:55 -07001582 drvdata->buf = drvdata->vaddr;
Pratik Patelb46038f2012-07-22 23:09:11 -07001583 drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
Pushkar Joshibf213a02013-05-03 13:18:44 -07001584 if (pdev->dev.of_node)
1585 drvdata->byte_cntr_present = !of_property_read_bool
1586 (pdev->dev.of_node,
1587 "qcom,byte-cntr-absent");
1588 ret = tmc_etr_byte_cntr_init(pdev, drvdata);
Pratik Patelb46038f2012-07-22 23:09:11 -07001589 if (ret)
1590 goto err0;
Pushkar Joshibf213a02013-05-03 13:18:44 -07001591 ret = tmc_etr_bam_init(pdev, drvdata);
1592 if (ret)
1593 goto err1;
Pratik Patel22911492012-06-25 21:38:02 -07001594 } else {
Pratik Patele411ac72012-10-31 16:38:05 -07001595 baddr = devm_kzalloc(dev, PAGE_SIZE + drvdata->size,
1596 GFP_KERNEL);
Pratik Patel26477792012-09-07 01:35:36 -07001597 if (!baddr)
Pratik Patel22911492012-06-25 21:38:02 -07001598 return -ENOMEM;
Pratik Patel26477792012-09-07 01:35:36 -07001599 drvdata->buf = baddr + PAGE_SIZE;
1600 *(uint32_t *)(baddr + TMC_ETFETB_DUMP_VER_OFF) =
1601 TMC_ETFETB_DUMP_VER;
1602 dump.id = MSM_TMC_ETFETB + etfetb_count;
1603 dump.start_addr = virt_to_phys(baddr);
Pratik Patele411ac72012-10-31 16:38:05 -07001604 dump.end_addr = dump.start_addr + PAGE_SIZE + drvdata->size;
Pratik Patel26477792012-09-07 01:35:36 -07001605 ret = msm_dump_table_register(&dump);
Pratik Patel84750b22012-12-11 21:56:19 -08001606 /*
1607 * Don't free the buffer in case of error since it can still
1608 * be used to provide dump collection via the device node or
1609 * as part of abort.
Pratik Patel26477792012-09-07 01:35:36 -07001610 */
1611 if (ret)
1612 dev_info(dev, "TMC ETF-ETB dump setup failed\n");
1613 etfetb_count++;
Pratik Patel22911492012-06-25 21:38:02 -07001614 }
1615
Pratik Patel26477792012-09-07 01:35:36 -07001616 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
1617 if (baddr) {
Pratik Patel84750b22012-12-11 21:56:19 -08001618 drvdata->reg_buf = baddr + PAGE_SIZE;
Pratik Patel26477792012-09-07 01:35:36 -07001619 *(uint32_t *)(baddr + TMC_REG_DUMP_VER_OFF) = TMC_REG_DUMP_VER;
1620 dump.id = MSM_TMC0_REG + count;
1621 dump.start_addr = virt_to_phys(baddr);
1622 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
1623 ret = msm_dump_table_register(&dump);
Pratik Patel84750b22012-12-11 21:56:19 -08001624 /*
1625 * Don't free the buffer in case of error since it can still
1626 * be used to dump registers as part of abort to aid post crash
1627 * parsing.
1628 */
1629 if (ret)
Pratik Patel26477792012-09-07 01:35:36 -07001630 dev_info(dev, "TMC REG dump setup failed\n");
Pratik Patel26477792012-09-07 01:35:36 -07001631 } else {
1632 dev_info(dev, "TMC REG dump space allocation failed\n");
1633 }
1634 count++;
1635
Pratik Patel7c0b3722013-02-08 11:57:27 -08001636 if (pdev->dev.of_node) {
Pratik Patela5544162013-02-08 11:57:27 -08001637 drvdata->reset_flush_race = of_property_read_bool(
1638 pdev->dev.of_node,
1639 "qcom,reset-flush-race");
1640
Pratik Patel7c0b3722013-02-08 11:57:27 -08001641 ctidata = of_get_coresight_cti_data(dev, pdev->dev.of_node);
1642 if (IS_ERR(ctidata)) {
1643 dev_err(dev, "invalid cti data\n");
1644 } else if (ctidata && ctidata->nr_ctis == 2) {
1645 drvdata->cti_flush = coresight_cti_get(
1646 ctidata->names[0]);
1647 if (IS_ERR(drvdata->cti_flush))
1648 dev_err(dev, "failed to get flush cti\n");
1649
1650 drvdata->cti_reset = coresight_cti_get(
1651 ctidata->names[1]);
1652 if (IS_ERR(drvdata->cti_reset))
1653 dev_err(dev, "failed to get reset cti\n");
1654 }
1655 }
1656
Pratik Patel22911492012-06-25 21:38:02 -07001657 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
1658 if (!desc) {
1659 ret = -ENOMEM;
Pushkar Joshibf213a02013-05-03 13:18:44 -07001660 goto err2;
Pratik Patel22911492012-06-25 21:38:02 -07001661 }
1662 if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
1663 desc->type = CORESIGHT_DEV_TYPE_SINK;
1664 desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
1665 desc->ops = &tmc_etb_cs_ops;
1666 desc->pdata = pdev->dev.platform_data;
1667 desc->dev = &pdev->dev;
1668 desc->groups = tmc_etb_attr_grps;
1669 desc->owner = THIS_MODULE;
1670 drvdata->csdev = coresight_register(desc);
1671 if (IS_ERR(drvdata->csdev)) {
1672 ret = PTR_ERR(drvdata->csdev);
Pushkar Joshibf213a02013-05-03 13:18:44 -07001673 goto err2;
Pratik Patel22911492012-06-25 21:38:02 -07001674 }
1675 } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
1676 desc->type = CORESIGHT_DEV_TYPE_SINK;
1677 desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
1678 desc->ops = &tmc_etr_cs_ops;
1679 desc->pdata = pdev->dev.platform_data;
1680 desc->dev = &pdev->dev;
1681 desc->groups = tmc_etr_attr_grps;
1682 desc->owner = THIS_MODULE;
1683 drvdata->csdev = coresight_register(desc);
1684 if (IS_ERR(drvdata->csdev)) {
1685 ret = PTR_ERR(drvdata->csdev);
Pushkar Joshibf213a02013-05-03 13:18:44 -07001686 goto err2;
Pratik Patel22911492012-06-25 21:38:02 -07001687 }
1688 } else {
1689 desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
1690 desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
1691 desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
1692 desc->ops = &tmc_etf_cs_ops;
1693 desc->pdata = pdev->dev.platform_data;
1694 desc->dev = &pdev->dev;
1695 desc->groups = tmc_etf_attr_grps;
1696 desc->owner = THIS_MODULE;
1697 drvdata->csdev = coresight_register(desc);
1698 if (IS_ERR(drvdata->csdev)) {
1699 ret = PTR_ERR(drvdata->csdev);
Pushkar Joshibf213a02013-05-03 13:18:44 -07001700 goto err2;
Pratik Patel22911492012-06-25 21:38:02 -07001701 }
1702 }
1703
1704 drvdata->miscdev.name = ((struct coresight_platform_data *)
1705 (pdev->dev.platform_data))->name;
1706 drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
1707 drvdata->miscdev.fops = &tmc_fops;
1708 ret = misc_register(&drvdata->miscdev);
1709 if (ret)
Pushkar Joshibf213a02013-05-03 13:18:44 -07001710 goto err3;
Pratik Patel22911492012-06-25 21:38:02 -07001711
1712 dev_info(dev, "TMC initialized\n");
1713 return 0;
Pushkar Joshibf213a02013-05-03 13:18:44 -07001714err3:
Pratik Patel22911492012-06-25 21:38:02 -07001715 coresight_unregister(drvdata->csdev);
Pushkar Joshibf213a02013-05-03 13:18:44 -07001716err2:
Pratik Patelb46038f2012-07-22 23:09:11 -07001717 tmc_etr_bam_exit(drvdata);
Pushkar Joshibf213a02013-05-03 13:18:44 -07001718err1:
1719 tmc_etr_byte_cntr_exit(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -07001720err0:
1721 free_contiguous_memory_by_paddr(drvdata->paddr);
1722 return ret;
1723}
1724
1725static int __devexit tmc_remove(struct platform_device *pdev)
1726{
1727 struct tmc_drvdata *drvdata = platform_get_drvdata(pdev);
1728
Pushkar Joshibf213a02013-05-03 13:18:44 -07001729 tmc_etr_byte_cntr_exit(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -07001730 misc_deregister(&drvdata->miscdev);
1731 coresight_unregister(drvdata->csdev);
Pratik Patelb46038f2012-07-22 23:09:11 -07001732 tmc_etr_bam_exit(drvdata);
Pratik Patel22911492012-06-25 21:38:02 -07001733 free_contiguous_memory_by_paddr(drvdata->paddr);
1734 return 0;
1735}
1736
1737static struct of_device_id tmc_match[] = {
1738 {.compatible = "arm,coresight-tmc"},
1739 {}
1740};
Pratik Patelfa896c92012-08-21 09:24:51 -07001741EXPORT_COMPAT("arm,coresight-tmc");
Pratik Patel22911492012-06-25 21:38:02 -07001742
1743static struct platform_driver tmc_driver = {
1744 .probe = tmc_probe,
1745 .remove = __devexit_p(tmc_remove),
1746 .driver = {
1747 .name = "coresight-tmc",
1748 .owner = THIS_MODULE,
1749 .of_match_table = tmc_match,
1750 },
1751};
1752
1753static int __init tmc_init(void)
1754{
1755 return platform_driver_register(&tmc_driver);
1756}
1757module_init(tmc_init);
1758
1759static void __exit tmc_exit(void)
1760{
1761 platform_driver_unregister(&tmc_driver);
1762}
1763module_exit(tmc_exit);
1764
1765MODULE_LICENSE("GPL v2");
1766MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver");