blob: 50bae5556b79b75a04b7c888da8d23d16ea89d77 [file] [log] [blame]
Pratik Patelef6da292012-09-17 17:37:19 -07001/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
Pratik Patel7831c082011-06-08 21:44:37 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
Pratik Patelcf418622011-09-22 11:15:11 -070015#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/device.h>
Pratik Patel7831c082011-06-08 21:44:37 -070018#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/err.h>
21#include <linux/fs.h>
Pratik Patel7831c082011-06-08 21:44:37 -070022#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/smp.h>
Pratik Patel7831c082011-06-08 21:44:37 -070025#include <linux/wakelock.h>
Pratik Patel6630ebe2012-03-06 16:44:22 -080026#include <linux/sysfs.h>
27#include <linux/stat.h>
Pratik Patel3b0ca882012-06-01 16:54:14 -070028#include <linux/mutex.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070029#include <linux/clk.h>
Pratik Patel5f6d1af2012-06-13 15:48:13 -070030#include <linux/of_coresight.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070031#include <linux/coresight.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080032#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080033#include <mach/socinfo.h>
Pratik Patel26477792012-09-07 01:35:36 -070034#include <mach/msm_memory_dump.h>
Pratik Patel7831c082011-06-08 21:44:37 -070035
Pratik Patel1746b8f2012-06-02 21:11:41 -070036#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070037
Pratik Patele6e41da2012-09-12 12:50:29 -070038#define etm_writel_mm(drvdata, val, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070039 __raw_writel((val), drvdata->base + off)
Pratik Patele6e41da2012-09-12 12:50:29 -070040#define etm_readl_mm(drvdata, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070041 __raw_readl(drvdata->base + off)
42
Pratik Patele6e41da2012-09-12 12:50:29 -070043#define etm_writel(drvdata, val, off) \
44({ \
45 if (cpu_is_krait_v3()) \
46 etm_writel_cp14(val, off); \
47 else \
48 etm_writel_mm(drvdata, val, off); \
49})
50#define etm_readl(drvdata, off) \
51({ \
52 uint32_t val; \
53 if (cpu_is_krait_v3()) \
54 val = etm_readl_cp14(off); \
55 else \
56 val = etm_readl_mm(drvdata, off); \
57 val; \
58})
59
Pratik Patel3b0ca882012-06-01 16:54:14 -070060#define ETM_LOCK(drvdata) \
61do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070062 /* recommended by spec to ensure ETM writes are committed prior
63 * to resuming execution
64 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070065 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070066 isb(); \
67 etm_writel_mm(drvdata, 0x0, CORESIGHT_LAR); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070068} while (0)
69#define ETM_UNLOCK(drvdata) \
70do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070071 etm_writel_mm(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
72 /* ensure unlock and any pending writes are committed prior to
73 * programming ETM registers
74 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070075 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070076 isb(); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070077} while (0)
78
Pratik Patel7831c082011-06-08 21:44:37 -070079/*
80 * Device registers:
81 * 0x000 - 0x2FC: Trace registers
82 * 0x300 - 0x314: Management registers
83 * 0x318 - 0xEFC: Trace registers
84 *
85 * Coresight registers
86 * 0xF00 - 0xF9C: Management registers
87 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
88 * Trace registers in PFTv1.1
89 * 0xFA8 - 0xFFC: Management registers
90 */
91
92/* Trace registers (0x000-0x2FC) */
93#define ETMCR (0x000)
94#define ETMCCR (0x004)
95#define ETMTRIGGER (0x008)
96#define ETMSR (0x010)
97#define ETMSCR (0x014)
98#define ETMTSSCR (0x018)
99#define ETMTEEVR (0x020)
100#define ETMTECR1 (0x024)
101#define ETMFFLR (0x02C)
102#define ETMACVRn(n) (0x040 + (n * 4))
103#define ETMACTRn(n) (0x080 + (n * 4))
104#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
105#define ETMCNTENRn(n) (0x150 + (n * 4))
106#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
107#define ETMCNTVRn(n) (0x170 + (n * 4))
108#define ETMSQ12EVR (0x180)
109#define ETMSQ21EVR (0x184)
110#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800111#define ETMSQ31EVR (0x18C)
112#define ETMSQ32EVR (0x190)
113#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -0700114#define ETMSQR (0x19C)
115#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
116#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
117#define ETMCIDCMR (0x1BC)
118#define ETMIMPSPEC0 (0x1C0)
119#define ETMIMPSPEC1 (0x1C4)
120#define ETMIMPSPEC2 (0x1C8)
121#define ETMIMPSPEC3 (0x1CC)
122#define ETMIMPSPEC4 (0x1D0)
123#define ETMIMPSPEC5 (0x1D4)
124#define ETMIMPSPEC6 (0x1D8)
125#define ETMIMPSPEC7 (0x1DC)
126#define ETMSYNCFR (0x1E0)
127#define ETMIDR (0x1E4)
128#define ETMCCER (0x1E8)
129#define ETMEXTINSELR (0x1EC)
130#define ETMTESSEICR (0x1F0)
131#define ETMEIBCR (0x1F4)
132#define ETMTSEVR (0x1F8)
133#define ETMAUXCR (0x1FC)
134#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800135#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700136/* Management registers (0x300-0x314) */
137#define ETMOSLAR (0x300)
138#define ETMOSLSR (0x304)
139#define ETMOSSRR (0x308)
140#define ETMPDCR (0x310)
141#define ETMPDSR (0x314)
142
Pratik Patel61de7302012-03-07 12:06:10 -0800143#define ETM_MAX_ADDR_CMP (16)
144#define ETM_MAX_CNTR (4)
145#define ETM_MAX_CTXID_CMP (3)
146
Pratik Patel6630ebe2012-03-06 16:44:22 -0800147#define ETM_MODE_EXCLUDE BIT(0)
148#define ETM_MODE_CYCACC BIT(1)
149#define ETM_MODE_STALL BIT(2)
150#define ETM_MODE_TIMESTAMP BIT(3)
151#define ETM_MODE_CTXID BIT(4)
152#define ETM_MODE_ALL (0x1F)
153
154#define ETM_EVENT_MASK (0x1FFFF)
155#define ETM_SYNC_MASK (0xFFF)
156#define ETM_ALL_MASK (0xFFFFFFFF)
157
158#define ETM_SEQ_STATE_MAX_VAL (0x2)
159
Pratik Patel26477792012-09-07 01:35:36 -0700160#define ETM_REG_DUMP_VER_OFF (4)
161#define ETM_REG_DUMP_VER (1)
162
Pratik Patel3b0ca882012-06-01 16:54:14 -0700163enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800164 ETM_ADDR_TYPE_NONE,
165 ETM_ADDR_TYPE_SINGLE,
166 ETM_ADDR_TYPE_RANGE,
167 ETM_ADDR_TYPE_START,
168 ETM_ADDR_TYPE_STOP,
169};
170
Pratik Patel29cba152012-01-03 11:40:26 -0800171#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700172static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800173#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700174static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800175#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700176module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700177 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700178);
179
Pratik Patel938e1ff2012-09-28 23:21:46 -0700180#ifdef CONFIG_MSM_QDSS_ETM_PCSAVE_DEFAULT_ENABLE
181static int boot_pcsave_enable = 1;
182#else
183static int boot_pcsave_enable;
184#endif
185module_param_named(
186 boot_pcsave_enable, boot_pcsave_enable, int, S_IRUGO
187);
188
Pratik Patel16aefdb2012-05-30 10:41:23 -0700189struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700190 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700191 struct device *dev;
192 struct coresight_device *csdev;
193 struct clk *clk;
194 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700195 struct wake_lock wake_lock;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700196 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800197 uint8_t arch;
198 uint8_t nr_addr_cmp;
199 uint8_t nr_cntr;
200 uint8_t nr_ext_inp;
201 uint8_t nr_ext_out;
202 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800203 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800204 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800205 uint32_t ctrl;
Pratik Patel938e1ff2012-09-28 23:21:46 -0700206 uint8_t ctrl_pwrdwn;
Pratik Patel61de7302012-03-07 12:06:10 -0800207 uint32_t trigger_event;
208 uint32_t startstop_ctrl;
209 uint32_t enable_event;
210 uint32_t enable_ctrl1;
211 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800212 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800213 uint32_t addr_val[ETM_MAX_ADDR_CMP];
214 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800215 uint32_t addr_type[ETM_MAX_ADDR_CMP];
216 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800217 uint32_t cntr_rld_val[ETM_MAX_CNTR];
218 uint32_t cntr_event[ETM_MAX_CNTR];
219 uint32_t cntr_rld_event[ETM_MAX_CNTR];
220 uint32_t cntr_val[ETM_MAX_CNTR];
221 uint32_t seq_12_event;
222 uint32_t seq_21_event;
223 uint32_t seq_23_event;
224 uint32_t seq_31_event;
225 uint32_t seq_32_event;
226 uint32_t seq_13_event;
227 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800228 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800229 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
230 uint32_t ctxid_mask;
231 uint32_t sync_freq;
232 uint32_t timestamp_event;
Pratik Patel938e1ff2012-09-28 23:21:46 -0700233 uint8_t pdcr_pwrup;
234 bool pcsave_impl;
235 bool pcsave_enable;
Pratik Patel7831c082011-06-08 21:44:37 -0700236};
237
Pratik Patelc14b4df2012-09-05 18:07:59 -0700238static struct etm_drvdata *etm0drvdata;
239
Pratik Pateld1d65c92012-09-25 23:37:43 -0700240/*
241 * ETM clock is derived from the processor clock and gets enabled on a
242 * logical OR of below items on Krait (v2 onwards):
Pratik Patel17f3b822011-11-21 12:41:47 -0800243 * 1.CPMR[ETMCLKEN] is 1
244 * 2.ETMCR[PD] is 0
245 * 3.ETMPDCR[PU] is 1
246 * 4.Reset is asserted (core or debug)
247 * 5.APB memory mapped requests (eg. EDAP access)
248 *
249 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
250 * enables
251 *
Pratik Pateld1d65c92012-09-25 23:37:43 -0700252 * We rely on 5. to be able to access ETMCR/ETMPDCR and then use 2./3. above
253 * for ETM clock vote in the driver and the save-restore code uses 1. above
Pratik Patel17f3b822011-11-21 12:41:47 -0800254 * for its vote
255 */
Pratik Pateld1d65c92012-09-25 23:37:43 -0700256static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
257{
258 uint32_t etmcr;
259
260 /* ensure pending cp14 accesses complete before setting pwrdwn */
261 mb();
262 isb();
263 etmcr = etm_readl(drvdata, ETMCR);
264 etmcr |= BIT(0);
265 etm_writel(drvdata, etmcr, ETMCR);
266}
267
268static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
269{
270 uint32_t etmcr;
271
272 etmcr = etm_readl(drvdata, ETMCR);
273 etmcr &= ~BIT(0);
274 etm_writel(drvdata, etmcr, ETMCR);
275 /* ensure pwrup completes before subsequent cp14 accesses */
276 mb();
277 isb();
278}
279
Pratik Patelef6da292012-09-17 17:37:19 -0700280static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700281{
Pratik Patelef6da292012-09-17 17:37:19 -0700282 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700283
Pratik Patele6e41da2012-09-12 12:50:29 -0700284 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700285 etmpdcr |= BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700286 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
287 /* ensure pwrup completes before subsequent cp14 accesses */
288 mb();
289 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700290}
291
Pratik Patelef6da292012-09-17 17:37:19 -0700292static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700293{
Pratik Patelef6da292012-09-17 17:37:19 -0700294 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700295
Pratik Patele6e41da2012-09-12 12:50:29 -0700296 /* ensure pending cp14 accesses complete before clearing pwrup */
297 mb();
298 isb();
299 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700300 etmpdcr &= ~BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700301 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700302}
303
Pratik Patel3b0ca882012-06-01 16:54:14 -0700304static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700305{
306 uint32_t etmcr;
307 int count;
308
Pratik Patel3b0ca882012-06-01 16:54:14 -0700309 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700310 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700311 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700312 /* recommended by spec for cp14 accesses to ensure etmcr write is
313 * complete before polling etmsr
314 */
315 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700316 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700317 && count > 0; count--)
318 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800319 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700320 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700321}
322
Pratik Patel3b0ca882012-06-01 16:54:14 -0700323static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700324{
325 uint32_t etmcr;
326 int count;
327
Pratik Patel3b0ca882012-06-01 16:54:14 -0700328 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700329 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700330 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700331 /* recommended by spec for cp14 accesses to ensure etmcr write is
332 * complete before polling etmsr
333 */
334 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700335 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700336 && count > 0; count--)
337 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800338 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700339 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700340}
341
Pratik Patel938e1ff2012-09-28 23:21:46 -0700342static void etm_save_pwrdwn(struct etm_drvdata *drvdata)
343{
344 drvdata->ctrl_pwrdwn = BVAL(etm_readl(drvdata, ETMCR), 0);
345}
346
347static void etm_restore_pwrdwn(struct etm_drvdata *drvdata)
348{
349 uint32_t etmcr;
350
351 etmcr = etm_readl(drvdata, ETMCR);
352 etmcr = (etmcr & ~BIT(0)) | drvdata->ctrl_pwrdwn;
353 etm_writel(drvdata, etmcr, ETMCR);
354}
355
356static void etm_save_pwrup(struct etm_drvdata *drvdata)
357{
358 drvdata->pdcr_pwrup = BVAL(etm_readl_mm(drvdata, ETMPDCR), 3);
359}
360
361static void etm_restore_pwrup(struct etm_drvdata *drvdata)
362{
363 uint32_t etmpdcr;
364
365 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
366 etmpdcr = (etmpdcr & ~BIT(3)) | (drvdata->pdcr_pwrup << 3);
367 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
368}
369
370static void etm_enable_pcsave(void *info)
371{
372 struct etm_drvdata *drvdata = info;
373
374 ETM_UNLOCK(drvdata);
375
376 etm_save_pwrup(drvdata);
377 /*
378 * ETMPDCR is only accessible via memory mapped interface and so use
379 * it first to enable power/clock to allow subsequent cp14 accesses.
380 */
381 etm_set_pwrup(drvdata);
382 etm_clr_pwrdwn(drvdata);
383 etm_restore_pwrup(drvdata);
384
385 ETM_LOCK(drvdata);
386}
387
388static void etm_disable_pcsave(void *info)
389{
390 struct etm_drvdata *drvdata = info;
391
392 ETM_UNLOCK(drvdata);
393
394 etm_save_pwrup(drvdata);
395 /*
396 * ETMPDCR is only accessible via memory mapped interface and so use
397 * it first to enable power/clock to allow subsequent cp14 accesses.
398 */
399 etm_set_pwrup(drvdata);
400 etm_set_pwrdwn(drvdata);
401 etm_restore_pwrup(drvdata);
402
403 ETM_LOCK(drvdata);
404}
405
Pratik Patel66e1a412012-09-06 11:07:06 -0700406static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700407{
Pratik Patel17f3b822011-11-21 12:41:47 -0800408 int i;
Pratik Pateld1d65c92012-09-25 23:37:43 -0700409 uint32_t etmcr;
Pratik Patel66e1a412012-09-06 11:07:06 -0700410 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700411
Pratik Patel3b0ca882012-06-01 16:54:14 -0700412 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700413 /*
414 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
415 * memory mapped interface and so use it first to enable power/clock
416 * to allow subsequent cp14 accesses.
417 */
Pratik Patelef6da292012-09-17 17:37:19 -0700418 etm_set_pwrup(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700419 etm_save_pwrdwn(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -0700420 /*
421 * Clear power down bit since when this bit is set writes to
422 * certain registers might be ignored.
423 */
424 etm_clr_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700425 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700426
Pratik Pateld1d65c92012-09-25 23:37:43 -0700427 etmcr = etm_readl(drvdata, ETMCR);
428 etmcr &= (BIT(10) | BIT(0));
429 etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700430 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
431 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
432 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
433 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
434 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700435 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700436 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
437 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700438 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700439 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700440 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
441 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
442 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700443 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700444 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800445 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700446 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
447 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
448 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
449 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
450 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
451 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
452 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700453 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700454 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700455 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700456 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
457 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
458 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
459 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
460 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
461 etm_writel(drvdata, 0x00000000, ETMAUXCR);
462 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
463 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800464
Pratik Patel3b0ca882012-06-01 16:54:14 -0700465 etm_clr_prog(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700466 etm_restore_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700467 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700468
469 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700470}
471
Pratik Patel3b0ca882012-06-01 16:54:14 -0700472static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700473{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700474 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
475 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800476
Pratik Patel16aefdb2012-05-30 10:41:23 -0700477 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700478
Pratik Patel16aefdb2012-05-30 10:41:23 -0700479 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700480 if (ret)
481 goto err_clk;
482
Pratik Patel3b0ca882012-06-01 16:54:14 -0700483 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700484 /* executing __etm_enable on the cpu whose ETM is being enabled
485 * ensures that register writes occur when cpu is powered.
486 */
487 smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700488 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700489
Pratik Patel16aefdb2012-05-30 10:41:23 -0700490 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700491
Pratik Patel16aefdb2012-05-30 10:41:23 -0700492 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700493 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700494err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700495 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800496 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700497}
498
Pratik Patel66e1a412012-09-06 11:07:06 -0700499static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700500{
Pratik Patel66e1a412012-09-06 11:07:06 -0700501 struct etm_drvdata *drvdata = info;
502
Pratik Patel3b0ca882012-06-01 16:54:14 -0700503 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700504 etm_save_pwrdwn(drvdata);
505 /*
506 * Clear power down bit since when this bit is set writes to
507 * certain registers might be ignored.
508 */
509 etm_clr_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700510 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700511
Pratik Patel17f3b822011-11-21 12:41:47 -0800512 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700513 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700514
Pratik Patel938e1ff2012-09-28 23:21:46 -0700515 etm_restore_pwrdwn(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800516 /* Vote for ETM power/clock disable */
Pratik Patelef6da292012-09-17 17:37:19 -0700517 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700518 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700519
520 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700521}
522
Pratik Patel3b0ca882012-06-01 16:54:14 -0700523static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700524{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700525 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800526
Pratik Patel16aefdb2012-05-30 10:41:23 -0700527 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700528
Pratik Patel3b0ca882012-06-01 16:54:14 -0700529 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700530 /* executing __etm_disable on the cpu whose ETM is being disabled
531 * ensures that register writes occur when cpu is powered.
532 */
533 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700534 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700535
Pratik Patel16aefdb2012-05-30 10:41:23 -0700536 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700537
Pratik Patel16aefdb2012-05-30 10:41:23 -0700538 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700539
Pratik Patel16aefdb2012-05-30 10:41:23 -0700540 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700541}
542
Pratik Patel3b0ca882012-06-01 16:54:14 -0700543static const struct coresight_ops_source etm_source_ops = {
544 .enable = etm_enable,
545 .disable = etm_disable,
546};
Pratik Patel17f3b822011-11-21 12:41:47 -0800547
Pratik Patel3b0ca882012-06-01 16:54:14 -0700548static const struct coresight_ops etm_cs_ops = {
549 .source_ops = &etm_source_ops,
550};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800551
Pratik Patela9c0e062012-05-28 13:45:35 -0700552static ssize_t etm_show_nr_addr_cmp(struct device *dev,
553 struct device_attribute *attr, char *buf)
554{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700555 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700556 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700557
Pratik Patela9c0e062012-05-28 13:45:35 -0700558 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
559}
560static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
561
562static ssize_t etm_show_nr_cntr(struct device *dev,
563 struct device_attribute *attr, char *buf)
564{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700565 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700566 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700567
Pratik Patela9c0e062012-05-28 13:45:35 -0700568 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
569}
570static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
571
572static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
573 struct device_attribute *attr, char *buf)
574{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700575 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700576 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700577
Pratik Patela9c0e062012-05-28 13:45:35 -0700578 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
579}
580static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
581
582static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
583 char *buf)
584{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700585 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700586 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700587
Pratik Patela9c0e062012-05-28 13:45:35 -0700588 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
589}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800590
Pratik Pateld30deda2012-02-01 14:40:55 -0800591/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700592static ssize_t etm_store_reset(struct device *dev,
593 struct device_attribute *attr, const char *buf,
594 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800595{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700596 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800597 int i;
598 unsigned long val;
599
600 if (sscanf(buf, "%lx", &val) != 1)
601 return -EINVAL;
602
Pratik Patel16aefdb2012-05-30 10:41:23 -0700603 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800604 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700605 drvdata->mode = ETM_MODE_EXCLUDE;
606 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800607 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700608 drvdata->mode |= ETM_MODE_CYCACC;
609 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800610 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700611 drvdata->trigger_event = 0x406F;
612 drvdata->startstop_ctrl = 0x0;
613 drvdata->enable_event = 0x6F;
614 drvdata->enable_ctrl1 = 0x1000000;
615 drvdata->fifofull_level = 0x28;
616 drvdata->addr_idx = 0x0;
617 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
618 drvdata->addr_val[i] = 0x0;
619 drvdata->addr_acctype[i] = 0x0;
620 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800621 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700622 drvdata->cntr_idx = 0x0;
623 for (i = 0; i < drvdata->nr_cntr; i++) {
624 drvdata->cntr_rld_val[i] = 0x0;
625 drvdata->cntr_event[i] = 0x406F;
626 drvdata->cntr_rld_event[i] = 0x406F;
627 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800628 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700629 drvdata->seq_12_event = 0x406F;
630 drvdata->seq_21_event = 0x406F;
631 drvdata->seq_23_event = 0x406F;
632 drvdata->seq_31_event = 0x406F;
633 drvdata->seq_32_event = 0x406F;
634 drvdata->seq_13_event = 0x406F;
635 drvdata->seq_curr_state = 0x0;
636 drvdata->ctxid_idx = 0x0;
637 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
638 drvdata->ctxid_val[i] = 0x0;
639 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700640 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
641 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
642 drvdata->sync_freq = 0x100;
643 else
644 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700645 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800646 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700647 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700648 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800649}
Pratik Patela9c0e062012-05-28 13:45:35 -0700650static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800651
Pratik Patela9c0e062012-05-28 13:45:35 -0700652static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
653 char *buf)
654{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700655 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700656 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700657
Pratik Patela9c0e062012-05-28 13:45:35 -0700658 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
659}
660
661static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
662 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800663{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700664 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800665 unsigned long val;
666
667 if (sscanf(buf, "%lx", &val) != 1)
668 return -EINVAL;
669
Pratik Patel16aefdb2012-05-30 10:41:23 -0700670 mutex_lock(&drvdata->mutex);
671 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800672
Pratik Patel16aefdb2012-05-30 10:41:23 -0700673 if (drvdata->mode & ETM_MODE_EXCLUDE)
674 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800675 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700676 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800677
Pratik Patel16aefdb2012-05-30 10:41:23 -0700678 if (drvdata->mode & ETM_MODE_CYCACC)
679 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800680 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700681 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800682
Pratik Patel16aefdb2012-05-30 10:41:23 -0700683 if (drvdata->mode & ETM_MODE_STALL)
684 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800685 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700686 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800687
Pratik Patel16aefdb2012-05-30 10:41:23 -0700688 if (drvdata->mode & ETM_MODE_TIMESTAMP)
689 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800690 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700691 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700692
Pratik Patel16aefdb2012-05-30 10:41:23 -0700693 if (drvdata->mode & ETM_MODE_CTXID)
694 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800695 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700696 drvdata->ctrl &= ~(BIT(14) | BIT(15));
697 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800698
Pratik Patela9c0e062012-05-28 13:45:35 -0700699 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800700}
Pratik Patela9c0e062012-05-28 13:45:35 -0700701static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800702
Pratik Patela9c0e062012-05-28 13:45:35 -0700703static ssize_t etm_show_trigger_event(struct device *dev,
704 struct device_attribute *attr, char *buf)
705{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700706 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700707 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700708
Pratik Patela9c0e062012-05-28 13:45:35 -0700709 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
710}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800711
Pratik Patela9c0e062012-05-28 13:45:35 -0700712static ssize_t etm_store_trigger_event(struct device *dev,
713 struct device_attribute *attr,
714 const char *buf, size_t size)
715{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700716 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700717 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800718
Pratik Patela9c0e062012-05-28 13:45:35 -0700719 if (sscanf(buf, "%lx", &val) != 1)
720 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800721
Pratik Patel16aefdb2012-05-30 10:41:23 -0700722 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700723 return size;
724}
725static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
726 etm_store_trigger_event);
727
728static ssize_t etm_show_enable_event(struct device *dev,
729 struct device_attribute *attr, char *buf)
730{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700731 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700732 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700733
Pratik Patela9c0e062012-05-28 13:45:35 -0700734 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
735}
736
737static ssize_t etm_store_enable_event(struct device *dev,
738 struct device_attribute *attr,
739 const char *buf, size_t size)
740{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700741 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700742 unsigned long val;
743
744 if (sscanf(buf, "%lx", &val) != 1)
745 return -EINVAL;
746
Pratik Patel16aefdb2012-05-30 10:41:23 -0700747 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700748 return size;
749}
750static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
751 etm_store_enable_event);
752
753static ssize_t etm_show_fifofull_level(struct device *dev,
754 struct device_attribute *attr, char *buf)
755{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700756 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700757 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700758
Pratik Patela9c0e062012-05-28 13:45:35 -0700759 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
760}
761
762static ssize_t etm_store_fifofull_level(struct device *dev,
763 struct device_attribute *attr,
764 const char *buf, size_t size)
765{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700766 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700767 unsigned long val;
768
769 if (sscanf(buf, "%lx", &val) != 1)
770 return -EINVAL;
771
Pratik Patel16aefdb2012-05-30 10:41:23 -0700772 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700773 return size;
774}
775static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
776 etm_store_fifofull_level);
777
778static ssize_t etm_show_addr_idx(struct device *dev,
779 struct device_attribute *attr, char *buf)
780{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700781 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700782 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700783
Pratik Patela9c0e062012-05-28 13:45:35 -0700784 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
785}
786
787static ssize_t etm_store_addr_idx(struct device *dev,
788 struct device_attribute *attr,
789 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800790{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700791 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800792 unsigned long val;
793
794 if (sscanf(buf, "%lx", &val) != 1)
795 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700796 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800797 return -EINVAL;
798
799 /* Use mutex to ensure index doesn't change while it gets dereferenced
800 * multiple times within a mutex block elsewhere.
801 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700802 mutex_lock(&drvdata->mutex);
803 drvdata->addr_idx = val;
804 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700805 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800806}
Pratik Patela9c0e062012-05-28 13:45:35 -0700807static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
808 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800809
Pratik Patela9c0e062012-05-28 13:45:35 -0700810static ssize_t etm_show_addr_single(struct device *dev,
811 struct device_attribute *attr, char *buf)
812{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700813 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700814 unsigned long val;
815 uint8_t idx;
816
Pratik Patel16aefdb2012-05-30 10:41:23 -0700817 mutex_lock(&drvdata->mutex);
818 idx = drvdata->addr_idx;
819 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
820 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
821 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700822 return -EPERM;
823 }
824
Pratik Patel16aefdb2012-05-30 10:41:23 -0700825 val = drvdata->addr_val[idx];
826 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700827 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
828}
829
830static ssize_t etm_store_addr_single(struct device *dev,
831 struct device_attribute *attr,
832 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800833{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700834 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800835 unsigned long val;
836 uint8_t idx;
837
838 if (sscanf(buf, "%lx", &val) != 1)
839 return -EINVAL;
840
Pratik Patel16aefdb2012-05-30 10:41:23 -0700841 mutex_lock(&drvdata->mutex);
842 idx = drvdata->addr_idx;
843 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
844 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
845 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800846 return -EPERM;
847 }
848
Pratik Patel16aefdb2012-05-30 10:41:23 -0700849 drvdata->addr_val[idx] = val;
850 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
851 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700852 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800853}
Pratik Patela9c0e062012-05-28 13:45:35 -0700854static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
855 etm_store_addr_single);
856
857static ssize_t etm_show_addr_range(struct device *dev,
858 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800859{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700860 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700861 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800862 uint8_t idx;
863
Pratik Patel16aefdb2012-05-30 10:41:23 -0700864 mutex_lock(&drvdata->mutex);
865 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700866 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700867 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700868 return -EPERM;
869 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700870 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
871 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
872 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
873 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
874 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800875 return -EPERM;
876 }
877
Pratik Patel16aefdb2012-05-30 10:41:23 -0700878 val1 = drvdata->addr_val[idx];
879 val2 = drvdata->addr_val[idx + 1];
880 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700881 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800882}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800883
Pratik Patela9c0e062012-05-28 13:45:35 -0700884static ssize_t etm_store_addr_range(struct device *dev,
885 struct device_attribute *attr,
886 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800887{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700888 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800889 unsigned long val1, val2;
890 uint8_t idx;
891
892 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
893 return -EINVAL;
894 /* lower address comparator cannot have a higher address value */
895 if (val1 > val2)
896 return -EINVAL;
897
Pratik Patel16aefdb2012-05-30 10:41:23 -0700898 mutex_lock(&drvdata->mutex);
899 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800900 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700901 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800902 return -EPERM;
903 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700904 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
905 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
906 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
907 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
908 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800909 return -EPERM;
910 }
911
Pratik Patel16aefdb2012-05-30 10:41:23 -0700912 drvdata->addr_val[idx] = val1;
913 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
914 drvdata->addr_val[idx + 1] = val2;
915 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
916 drvdata->enable_ctrl1 |= (1 << (idx/2));
917 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700918 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800919}
Pratik Patela9c0e062012-05-28 13:45:35 -0700920static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
921 etm_store_addr_range);
922
923static ssize_t etm_show_addr_start(struct device *dev,
924 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800925{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700926 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700927 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800928 uint8_t idx;
929
Pratik Patel16aefdb2012-05-30 10:41:23 -0700930 mutex_lock(&drvdata->mutex);
931 idx = drvdata->addr_idx;
932 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
933 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
934 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800935 return -EPERM;
936 }
937
Pratik Patel16aefdb2012-05-30 10:41:23 -0700938 val = drvdata->addr_val[idx];
939 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700940 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800941}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800942
Pratik Patela9c0e062012-05-28 13:45:35 -0700943static ssize_t etm_store_addr_start(struct device *dev,
944 struct device_attribute *attr,
945 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800946{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700947 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800948 unsigned long val;
949 uint8_t idx;
950
951 if (sscanf(buf, "%lx", &val) != 1)
952 return -EINVAL;
953
Pratik Patel16aefdb2012-05-30 10:41:23 -0700954 mutex_lock(&drvdata->mutex);
955 idx = drvdata->addr_idx;
956 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
957 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
958 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800959 return -EPERM;
960 }
961
Pratik Patel16aefdb2012-05-30 10:41:23 -0700962 drvdata->addr_val[idx] = val;
963 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
964 drvdata->startstop_ctrl |= (1 << idx);
965 drvdata->enable_ctrl1 |= BIT(25);
966 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700967 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800968}
Pratik Patela9c0e062012-05-28 13:45:35 -0700969static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
970 etm_store_addr_start);
971
972static ssize_t etm_show_addr_stop(struct device *dev,
973 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800974{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700975 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800976 unsigned long val;
977 uint8_t idx;
978
Pratik Patel16aefdb2012-05-30 10:41:23 -0700979 mutex_lock(&drvdata->mutex);
980 idx = drvdata->addr_idx;
981 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
982 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
983 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800984 return -EPERM;
985 }
986
Pratik Patel16aefdb2012-05-30 10:41:23 -0700987 val = drvdata->addr_val[idx];
988 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800989 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
990}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800991
Pratik Patela9c0e062012-05-28 13:45:35 -0700992static ssize_t etm_store_addr_stop(struct device *dev,
993 struct device_attribute *attr,
994 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800995{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700996 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800997 unsigned long val;
998 uint8_t idx;
999
1000 if (sscanf(buf, "%lx", &val) != 1)
1001 return -EINVAL;
1002
Pratik Patel16aefdb2012-05-30 10:41:23 -07001003 mutex_lock(&drvdata->mutex);
1004 idx = drvdata->addr_idx;
1005 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1006 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
1007 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001008 return -EPERM;
1009 }
1010
Pratik Patel16aefdb2012-05-30 10:41:23 -07001011 drvdata->addr_val[idx] = val;
1012 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
1013 drvdata->startstop_ctrl |= (1 << (idx + 16));
1014 drvdata->enable_ctrl1 |= BIT(25);
1015 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001016 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001017}
Pratik Patela9c0e062012-05-28 13:45:35 -07001018static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
1019 etm_store_addr_stop);
1020
1021static ssize_t etm_show_addr_acctype(struct device *dev,
1022 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001023{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001024 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001025 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001026
Pratik Patel16aefdb2012-05-30 10:41:23 -07001027 mutex_lock(&drvdata->mutex);
1028 val = drvdata->addr_acctype[drvdata->addr_idx];
1029 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001030 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1031}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001032
Pratik Patela9c0e062012-05-28 13:45:35 -07001033static ssize_t etm_store_addr_acctype(struct device *dev,
1034 struct device_attribute *attr,
1035 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001036{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001037 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001038 unsigned long val;
1039
1040 if (sscanf(buf, "%lx", &val) != 1)
1041 return -EINVAL;
1042
Pratik Patel16aefdb2012-05-30 10:41:23 -07001043 mutex_lock(&drvdata->mutex);
1044 drvdata->addr_acctype[drvdata->addr_idx] = val;
1045 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001046 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001047}
Pratik Patela9c0e062012-05-28 13:45:35 -07001048static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
1049 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001050
Pratik Patela9c0e062012-05-28 13:45:35 -07001051static ssize_t etm_show_cntr_idx(struct device *dev,
1052 struct device_attribute *attr, char *buf)
1053{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001054 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001055 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001056
Pratik Patel6630ebe2012-03-06 16:44:22 -08001057 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1058}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001059
Pratik Patela9c0e062012-05-28 13:45:35 -07001060static ssize_t etm_store_cntr_idx(struct device *dev,
1061 struct device_attribute *attr,
1062 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001063{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001064 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001065 unsigned long val;
1066
1067 if (sscanf(buf, "%lx", &val) != 1)
1068 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001069 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001070 return -EINVAL;
1071
1072 /* Use mutex to ensure index doesn't change while it gets dereferenced
1073 * multiple times within a mutex block elsewhere.
1074 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001075 mutex_lock(&drvdata->mutex);
1076 drvdata->cntr_idx = val;
1077 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001078 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001079}
Pratik Patela9c0e062012-05-28 13:45:35 -07001080static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
1081 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001082
Pratik Patela9c0e062012-05-28 13:45:35 -07001083static ssize_t etm_show_cntr_rld_val(struct device *dev,
1084 struct device_attribute *attr, char *buf)
1085{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001086 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001087 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001088
Pratik Patel16aefdb2012-05-30 10:41:23 -07001089 mutex_lock(&drvdata->mutex);
1090 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
1091 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001092 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1093}
1094
1095static ssize_t etm_store_cntr_rld_val(struct device *dev,
1096 struct device_attribute *attr,
1097 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001098{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001099 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001100 unsigned long val;
1101
1102 if (sscanf(buf, "%lx", &val) != 1)
1103 return -EINVAL;
1104
Pratik Patel16aefdb2012-05-30 10:41:23 -07001105 mutex_lock(&drvdata->mutex);
1106 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
1107 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001108 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001109}
Pratik Patela9c0e062012-05-28 13:45:35 -07001110static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
1111 etm_store_cntr_rld_val);
1112
1113static ssize_t etm_show_cntr_event(struct device *dev,
1114 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001115{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001116 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001117 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001118
Pratik Patel16aefdb2012-05-30 10:41:23 -07001119 mutex_lock(&drvdata->mutex);
1120 val = drvdata->cntr_event[drvdata->cntr_idx];
1121 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001122 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1123}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001124
Pratik Patela9c0e062012-05-28 13:45:35 -07001125static ssize_t etm_store_cntr_event(struct device *dev,
1126 struct device_attribute *attr,
1127 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001128{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001129 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001130 unsigned long val;
1131
1132 if (sscanf(buf, "%lx", &val) != 1)
1133 return -EINVAL;
1134
Pratik Patel16aefdb2012-05-30 10:41:23 -07001135 mutex_lock(&drvdata->mutex);
1136 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1137 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001138 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001139}
Pratik Patela9c0e062012-05-28 13:45:35 -07001140static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1141 etm_store_cntr_event);
1142
1143static ssize_t etm_show_cntr_rld_event(struct device *dev,
1144 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001145{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001146 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001147 unsigned long val;
1148
Pratik Patel16aefdb2012-05-30 10:41:23 -07001149 mutex_lock(&drvdata->mutex);
1150 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
1151 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001152 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1153}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001154
Pratik Patela9c0e062012-05-28 13:45:35 -07001155static ssize_t etm_store_cntr_rld_event(struct device *dev,
1156 struct device_attribute *attr,
1157 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001158{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001159 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001160 unsigned long val;
1161
1162 if (sscanf(buf, "%lx", &val) != 1)
1163 return -EINVAL;
1164
Pratik Patel16aefdb2012-05-30 10:41:23 -07001165 mutex_lock(&drvdata->mutex);
1166 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1167 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001168 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001169}
Pratik Patela9c0e062012-05-28 13:45:35 -07001170static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1171 etm_store_cntr_rld_event);
1172
1173static ssize_t etm_show_cntr_val(struct device *dev,
1174 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001175{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001176 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001177 unsigned long val;
1178
Pratik Patel16aefdb2012-05-30 10:41:23 -07001179 mutex_lock(&drvdata->mutex);
1180 val = drvdata->cntr_val[drvdata->cntr_idx];
1181 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001182 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1183}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001184
Pratik Patela9c0e062012-05-28 13:45:35 -07001185static ssize_t etm_store_cntr_val(struct device *dev,
1186 struct device_attribute *attr,
1187 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001188{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001189 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001190 unsigned long val;
1191
1192 if (sscanf(buf, "%lx", &val) != 1)
1193 return -EINVAL;
1194
Pratik Patel16aefdb2012-05-30 10:41:23 -07001195 mutex_lock(&drvdata->mutex);
1196 drvdata->cntr_val[drvdata->cntr_idx] = val;
1197 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001198 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001199}
Pratik Patela9c0e062012-05-28 13:45:35 -07001200static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1201 etm_store_cntr_val);
1202
1203static ssize_t etm_show_seq_12_event(struct device *dev,
1204 struct device_attribute *attr, char *buf)
1205{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001206 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001207 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001208
Pratik Patela9c0e062012-05-28 13:45:35 -07001209 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1210}
1211
1212static ssize_t etm_store_seq_12_event(struct device *dev,
1213 struct device_attribute *attr,
1214 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001215{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001216 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001217 unsigned long val;
1218
Pratik Patela9c0e062012-05-28 13:45:35 -07001219 if (sscanf(buf, "%lx", &val) != 1)
1220 return -EINVAL;
1221
Pratik Patel16aefdb2012-05-30 10:41:23 -07001222 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001223 return size;
1224}
1225static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1226 etm_store_seq_12_event);
1227
1228static ssize_t etm_show_seq_21_event(struct device *dev,
1229 struct device_attribute *attr, char *buf)
1230{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001231 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001232 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001233
Pratik Patel6630ebe2012-03-06 16:44:22 -08001234 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1235}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001236
Pratik Patela9c0e062012-05-28 13:45:35 -07001237static ssize_t etm_store_seq_21_event(struct device *dev,
1238 struct device_attribute *attr,
1239 const char *buf, size_t size)
1240{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001241 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001242 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001243
Pratik Patela9c0e062012-05-28 13:45:35 -07001244 if (sscanf(buf, "%lx", &val) != 1)
1245 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001246
Pratik Patel16aefdb2012-05-30 10:41:23 -07001247 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001248 return size;
1249}
1250static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1251 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001252
Pratik Patela9c0e062012-05-28 13:45:35 -07001253static ssize_t etm_show_seq_23_event(struct device *dev,
1254 struct device_attribute *attr, char *buf)
1255{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001256 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001257 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001258
Pratik Patela9c0e062012-05-28 13:45:35 -07001259 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1260}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001261
Pratik Patela9c0e062012-05-28 13:45:35 -07001262static ssize_t etm_store_seq_23_event(struct device *dev,
1263 struct device_attribute *attr,
1264 const char *buf, size_t size)
1265{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001266 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001267 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001268
Pratik Patela9c0e062012-05-28 13:45:35 -07001269 if (sscanf(buf, "%lx", &val) != 1)
1270 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001271
Pratik Patel16aefdb2012-05-30 10:41:23 -07001272 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001273 return size;
1274}
1275static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1276 etm_store_seq_23_event);
1277
1278static ssize_t etm_show_seq_31_event(struct device *dev,
1279 struct device_attribute *attr, char *buf)
1280{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001281 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001282 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001283
Pratik Patela9c0e062012-05-28 13:45:35 -07001284 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1285}
1286
1287static ssize_t etm_store_seq_31_event(struct device *dev,
1288 struct device_attribute *attr,
1289 const char *buf, size_t size)
1290{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001291 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001292 unsigned long val;
1293
1294 if (sscanf(buf, "%lx", &val) != 1)
1295 return -EINVAL;
1296
Pratik Patel16aefdb2012-05-30 10:41:23 -07001297 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001298 return size;
1299}
1300static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1301 etm_store_seq_31_event);
1302
1303static ssize_t etm_show_seq_32_event(struct device *dev,
1304 struct device_attribute *attr, char *buf)
1305{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001306 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001307 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001308
Pratik Patela9c0e062012-05-28 13:45:35 -07001309 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1310}
1311
1312static ssize_t etm_store_seq_32_event(struct device *dev,
1313 struct device_attribute *attr,
1314 const char *buf, size_t size)
1315{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001316 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001317 unsigned long val;
1318
1319 if (sscanf(buf, "%lx", &val) != 1)
1320 return -EINVAL;
1321
Pratik Patel16aefdb2012-05-30 10:41:23 -07001322 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001323 return size;
1324}
1325static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1326 etm_store_seq_32_event);
1327
1328static ssize_t etm_show_seq_13_event(struct device *dev,
1329 struct device_attribute *attr, char *buf)
1330{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001331 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001332 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001333
Pratik Patela9c0e062012-05-28 13:45:35 -07001334 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1335}
1336
1337static ssize_t etm_store_seq_13_event(struct device *dev,
1338 struct device_attribute *attr,
1339 const char *buf, size_t size)
1340{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001341 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001342 unsigned long val;
1343
1344 if (sscanf(buf, "%lx", &val) != 1)
1345 return -EINVAL;
1346
Pratik Patel16aefdb2012-05-30 10:41:23 -07001347 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001348 return size;
1349}
1350static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1351 etm_store_seq_13_event);
1352
1353static ssize_t etm_show_seq_curr_state(struct device *dev,
1354 struct device_attribute *attr, char *buf)
1355{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001356 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001357 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001358
Pratik Patela9c0e062012-05-28 13:45:35 -07001359 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1360}
1361
1362static ssize_t etm_store_seq_curr_state(struct device *dev,
1363 struct device_attribute *attr,
1364 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001365{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001366 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001367 unsigned long val;
1368
1369 if (sscanf(buf, "%lx", &val) != 1)
1370 return -EINVAL;
1371 if (val > ETM_SEQ_STATE_MAX_VAL)
1372 return -EINVAL;
1373
Pratik Patel16aefdb2012-05-30 10:41:23 -07001374 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001375 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001376}
Pratik Patela9c0e062012-05-28 13:45:35 -07001377static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1378 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001379
Pratik Patela9c0e062012-05-28 13:45:35 -07001380static ssize_t etm_show_ctxid_idx(struct device *dev,
1381 struct device_attribute *attr, char *buf)
1382{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001383 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001384 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001385
Pratik Patela9c0e062012-05-28 13:45:35 -07001386 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1387}
1388
1389static ssize_t etm_store_ctxid_idx(struct device *dev,
1390 struct device_attribute *attr,
1391 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001392{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001393 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001394 unsigned long val;
1395
1396 if (sscanf(buf, "%lx", &val) != 1)
1397 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001398 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001399 return -EINVAL;
1400
1401 /* Use mutex to ensure index doesn't change while it gets dereferenced
1402 * multiple times within a mutex block elsewhere.
1403 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001404 mutex_lock(&drvdata->mutex);
1405 drvdata->ctxid_idx = val;
1406 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001407 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001408}
Pratik Patela9c0e062012-05-28 13:45:35 -07001409static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1410 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001411
Pratik Patela9c0e062012-05-28 13:45:35 -07001412static ssize_t etm_show_ctxid_val(struct device *dev,
1413 struct device_attribute *attr, char *buf)
1414{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001415 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001416 unsigned long val;
1417
Pratik Patel16aefdb2012-05-30 10:41:23 -07001418 mutex_lock(&drvdata->mutex);
1419 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1420 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001421 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1422}
1423
1424static ssize_t etm_store_ctxid_val(struct device *dev,
1425 struct device_attribute *attr,
1426 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001427{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001428 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001429 unsigned long val;
1430
1431 if (sscanf(buf, "%lx", &val) != 1)
1432 return -EINVAL;
1433
Pratik Patel16aefdb2012-05-30 10:41:23 -07001434 mutex_lock(&drvdata->mutex);
1435 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1436 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001437 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001438}
Pratik Patela9c0e062012-05-28 13:45:35 -07001439static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1440 etm_store_ctxid_val);
1441
1442static ssize_t etm_show_ctxid_mask(struct device *dev,
1443 struct device_attribute *attr, char *buf)
1444{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001445 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001446 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001447
Pratik Patela9c0e062012-05-28 13:45:35 -07001448 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1449}
1450
1451static ssize_t etm_store_ctxid_mask(struct device *dev,
1452 struct device_attribute *attr,
1453 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001454{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001455 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001456 unsigned long val;
1457
Pratik Patela9c0e062012-05-28 13:45:35 -07001458 if (sscanf(buf, "%lx", &val) != 1)
1459 return -EINVAL;
1460
Pratik Patel16aefdb2012-05-30 10:41:23 -07001461 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001462 return size;
1463}
1464static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1465 etm_store_ctxid_mask);
1466
1467static ssize_t etm_show_sync_freq(struct device *dev,
1468 struct device_attribute *attr, char *buf)
1469{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001470 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001471 unsigned long val = drvdata->sync_freq;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001472
Pratik Patel6630ebe2012-03-06 16:44:22 -08001473 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1474}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001475
Pratik Patela9c0e062012-05-28 13:45:35 -07001476static ssize_t etm_store_sync_freq(struct device *dev,
1477 struct device_attribute *attr,
1478 const char *buf, size_t size)
1479{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001480 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001481 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001482
Pratik Patela9c0e062012-05-28 13:45:35 -07001483 if (sscanf(buf, "%lx", &val) != 1)
1484 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001485
Pratik Patel16aefdb2012-05-30 10:41:23 -07001486 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001487 return size;
1488}
1489static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1490 etm_store_sync_freq);
1491
1492static ssize_t etm_show_timestamp_event(struct device *dev,
1493 struct device_attribute *attr,
1494 char *buf)
1495{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001496 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001497 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001498
Pratik Patela9c0e062012-05-28 13:45:35 -07001499 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1500}
1501
1502static ssize_t etm_store_timestamp_event(struct device *dev,
1503 struct device_attribute *attr,
1504 const char *buf, size_t size)
1505{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001506 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001507 unsigned long val;
1508
1509 if (sscanf(buf, "%lx", &val) != 1)
1510 return -EINVAL;
1511
Pratik Patel16aefdb2012-05-30 10:41:23 -07001512 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001513 return size;
1514}
1515static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1516 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001517
Pratik Patel938e1ff2012-09-28 23:21:46 -07001518static ssize_t etm_show_pcsave(struct device *dev,
1519 struct device_attribute *attr, char *buf)
1520{
1521 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1522 unsigned long val;
1523
1524 val = drvdata->pcsave_enable;
1525 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1526}
1527
1528static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
1529{
1530 int ret;
1531
1532 ret = clk_prepare_enable(drvdata->clk);
1533 if (ret)
1534 return ret;
1535
1536 mutex_lock(&drvdata->mutex);
1537 if (val) {
1538 smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
1539 drvdata, 1);
1540 drvdata->pcsave_enable = true;
1541 } else {
1542 smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
1543 drvdata, 1);
1544 drvdata->pcsave_enable = false;
1545 }
1546 mutex_unlock(&drvdata->mutex);
1547
1548 clk_disable_unprepare(drvdata->clk);
1549 return 0;
1550}
1551
1552static ssize_t etm_store_pcsave(struct device *dev,
1553 struct device_attribute *attr,
1554 const char *buf, size_t size)
1555{
1556 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1557 unsigned long val;
1558 int ret;
1559
1560 if (sscanf(buf, "%lx", &val) != 1)
1561 return -EINVAL;
1562
1563 ret = __etm_store_pcsave(drvdata, val);
1564 if (ret)
1565 return ret;
1566
1567 return size;
1568}
1569static DEVICE_ATTR(pcsave, S_IRUGO | S_IWUSR, etm_show_pcsave,
1570 etm_store_pcsave);
1571
Pratik Patel6630ebe2012-03-06 16:44:22 -08001572static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001573 &dev_attr_nr_addr_cmp.attr,
1574 &dev_attr_nr_cntr.attr,
1575 &dev_attr_nr_ctxid_cmp.attr,
1576 &dev_attr_reset.attr,
1577 &dev_attr_mode.attr,
1578 &dev_attr_trigger_event.attr,
1579 &dev_attr_enable_event.attr,
1580 &dev_attr_fifofull_level.attr,
1581 &dev_attr_addr_idx.attr,
1582 &dev_attr_addr_single.attr,
1583 &dev_attr_addr_range.attr,
1584 &dev_attr_addr_start.attr,
1585 &dev_attr_addr_stop.attr,
1586 &dev_attr_addr_acctype.attr,
1587 &dev_attr_cntr_idx.attr,
1588 &dev_attr_cntr_rld_val.attr,
1589 &dev_attr_cntr_event.attr,
1590 &dev_attr_cntr_rld_event.attr,
1591 &dev_attr_cntr_val.attr,
1592 &dev_attr_seq_12_event.attr,
1593 &dev_attr_seq_21_event.attr,
1594 &dev_attr_seq_23_event.attr,
1595 &dev_attr_seq_31_event.attr,
1596 &dev_attr_seq_32_event.attr,
1597 &dev_attr_seq_13_event.attr,
1598 &dev_attr_seq_curr_state.attr,
1599 &dev_attr_ctxid_idx.attr,
1600 &dev_attr_ctxid_val.attr,
1601 &dev_attr_ctxid_mask.attr,
1602 &dev_attr_sync_freq.attr,
1603 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001604 NULL,
1605};
1606
1607static struct attribute_group etm_attr_grp = {
1608 .attrs = etm_attrs,
1609};
1610
Pratik Patel3b0ca882012-06-01 16:54:14 -07001611static const struct attribute_group *etm_attr_grps[] = {
1612 &etm_attr_grp,
1613 NULL,
1614};
1615
1616/* Memory mapped writes to clear os lock not supported */
1617static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001618{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001619 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001620
Pratik Patel3b0ca882012-06-01 16:54:14 -07001621 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1622 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001623}
1624
Stephen Boyda9510502012-04-24 16:23:34 -07001625static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001626{
Pratik Patel61de7302012-03-07 12:06:10 -08001627 switch (arch) {
1628 case PFT_ARCH_V1_1:
1629 break;
1630 default:
1631 return false;
1632 }
1633 return true;
1634}
1635
Pratik Patele6e41da2012-09-12 12:50:29 -07001636static void __devinit etm_prepare_arch(struct etm_drvdata *drvdata)
1637{
1638 /* Unlock OS lock first to allow memory mapped reads and writes. This
1639 * is required for Krait pass1
1640 * */
1641 etm_os_unlock(NULL);
1642 smp_call_function(etm_os_unlock, NULL, 1);
1643}
1644
1645static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001646{
Pratik Patel61de7302012-03-07 12:06:10 -08001647 uint32_t etmidr;
1648 uint32_t etmccr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001649 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001650
Pratik Patel3b0ca882012-06-01 16:54:14 -07001651 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001652 /*
1653 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
1654 * memory mapped interface and so use it first to enable power/clock
1655 * to allow subsequent cp14 accesses.
1656 */
Pratik Patelef6da292012-09-17 17:37:19 -07001657 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -07001658 /*
1659 * Clear power down bit since when this bit is set writes to
1660 * certain registers might be ignored.
1661 */
1662 etm_clr_pwrdwn(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001663 /* Set prog bit. It will be set from reset but this is included to
1664 * ensure it is set
1665 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001666 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001667
1668 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001669 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001670 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001671
Pratik Patel3b0ca882012-06-01 16:54:14 -07001672 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001673 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1674 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1675 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1676 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1677 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001678
Pratik Pateld1d65c92012-09-25 23:37:43 -07001679 etm_set_pwrdwn(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001680 /* Vote for ETM power/clock disable */
Pratik Patelef6da292012-09-17 17:37:19 -07001681 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001682 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001683}
1684
Pratik Patelc14b4df2012-09-05 18:07:59 -07001685static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1686{
1687 drvdata->arch = etm0drvdata->arch;
1688 drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
1689 drvdata->nr_cntr = etm0drvdata->nr_cntr;
1690 drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
1691 drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
1692 drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
1693}
1694
Pratik Patel3b0ca882012-06-01 16:54:14 -07001695static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001696{
1697 int i;
1698
1699 drvdata->trigger_event = 0x406F;
1700 drvdata->enable_event = 0x6F;
1701 drvdata->enable_ctrl1 = 0x1;
1702 drvdata->fifofull_level = 0x28;
1703 if (drvdata->nr_addr_cmp >= 2) {
1704 drvdata->addr_val[0] = (uint32_t) _stext;
1705 drvdata->addr_val[1] = (uint32_t) _etext;
1706 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1707 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1708 }
1709 for (i = 0; i < drvdata->nr_cntr; i++) {
1710 drvdata->cntr_event[i] = 0x406F;
1711 drvdata->cntr_rld_event[i] = 0x406F;
1712 }
1713 drvdata->seq_12_event = 0x406F;
1714 drvdata->seq_21_event = 0x406F;
1715 drvdata->seq_23_event = 0x406F;
1716 drvdata->seq_31_event = 0x406F;
1717 drvdata->seq_32_event = 0x406F;
1718 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001719 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1720 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1721 drvdata->sync_freq = 0x100;
1722 else
1723 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001724 drvdata->timestamp_event = 0x406F;
1725
1726 /* Overrides for Krait pass1 */
1727 if (cpu_is_krait_v1()) {
1728 /* Krait pass1 doesn't support include filtering and non-cycle
1729 * accurate tracing
1730 */
1731 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1732 drvdata->ctrl = 0x1000;
1733 drvdata->enable_ctrl1 = 0x1000000;
1734 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1735 drvdata->addr_val[i] = 0x0;
1736 drvdata->addr_acctype[i] = 0x0;
1737 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1738 }
1739 }
1740}
1741
Pratik Patel492b3012012-03-06 14:22:30 -08001742static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001743{
Pratik Patele5771792011-09-17 18:33:54 -07001744 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001745 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001746 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001747 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001748 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07001749 uint32_t reg_size;
1750 static int count;
1751 void *baddr;
1752 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001753 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001754
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001755 if (pdev->dev.of_node) {
1756 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1757 if (IS_ERR(pdata))
1758 return PTR_ERR(pdata);
1759 pdev->dev.platform_data = pdata;
1760 }
1761
Pratik Patel4a1b2522012-06-17 15:31:15 -07001762 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1763 if (!drvdata)
1764 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001765 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001766 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001767
Pratik Patel4a1b2522012-06-17 15:31:15 -07001768 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1769 if (!res)
1770 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07001771 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07001772
Pratik Patel4a1b2522012-06-17 15:31:15 -07001773 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1774 if (!drvdata->base)
1775 return -ENOMEM;
1776
Pratik Patel16aefdb2012-05-30 10:41:23 -07001777 mutex_init(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001778 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07001779
Pratik Patel4a1b2522012-06-17 15:31:15 -07001780 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001781 if (IS_ERR(drvdata->clk)) {
1782 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001783 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001784 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001785
Pratik Patel6fb38342012-06-03 14:51:38 -07001786 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001787 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001788 goto err0;
1789
Pratik Patel26477792012-09-07 01:35:36 -07001790 drvdata->cpu = count++;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001791
Pratik Patel16aefdb2012-05-30 10:41:23 -07001792 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001793 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001794 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001795
Pratik Patelc14b4df2012-09-05 18:07:59 -07001796 /* Use CPU0 to populate read-only configuration data for ETM0. For other
1797 * ETMs copy it over from ETM0.
1798 */
1799 if (drvdata->cpu == 0) {
Pratik Patele6e41da2012-09-12 12:50:29 -07001800 etm_prepare_arch(drvdata);
1801 smp_call_function_single(drvdata->cpu, etm_init_arch_data,
1802 drvdata, 1);
Pratik Patelc14b4df2012-09-05 18:07:59 -07001803 etm0drvdata = drvdata;
1804 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001805 etm_copy_arch_data(drvdata);
1806 }
1807 if (etm_arch_supported(drvdata->arch) == false) {
1808 ret = -EINVAL;
1809 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001810 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001811 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001812
Pratik Patel16aefdb2012-05-30 10:41:23 -07001813 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001814
Pratik Patel26477792012-09-07 01:35:36 -07001815 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
1816 if (baddr) {
1817 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
1818 dump.id = MSM_ETM0_REG + drvdata->cpu;
1819 dump.start_addr = virt_to_phys(baddr);
1820 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
1821 ret = msm_dump_table_register(&dump);
1822 if (ret) {
1823 devm_kfree(dev, baddr);
1824 dev_err(dev, "ETM REG dump setup failed\n");
1825 }
1826 } else {
1827 dev_err(dev, "ETM REG dump space allocation failed\n");
1828 }
1829
Pratik Patel4a1b2522012-06-17 15:31:15 -07001830 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001831 if (!desc) {
1832 ret = -ENOMEM;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001833 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001834 }
1835 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1836 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1837 desc->ops = &etm_cs_ops;
1838 desc->pdata = pdev->dev.platform_data;
1839 desc->dev = &pdev->dev;
1840 desc->groups = etm_attr_grps;
1841 desc->owner = THIS_MODULE;
1842 drvdata->csdev = coresight_register(desc);
1843 if (IS_ERR(drvdata->csdev)) {
1844 ret = PTR_ERR(drvdata->csdev);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001845 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001846 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001847
Pratik Patel938e1ff2012-09-28 23:21:46 -07001848 if (pdev->dev.of_node)
1849 drvdata->pcsave_impl = of_property_read_bool(pdev->dev.of_node,
1850 "qcom,pc-save");
1851 if (drvdata->pcsave_impl) {
1852 ret = device_create_file(&drvdata->csdev->dev,
1853 &dev_attr_pcsave);
1854 if (ret)
1855 dev_err(dev, "ETM pcsave dev node creation failed\n");
1856 }
1857
Pratik Patel4a1b2522012-06-17 15:31:15 -07001858 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001859
Pratik Patel3b0ca882012-06-01 16:54:14 -07001860 if (boot_enable)
1861 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001862
Pratik Patel938e1ff2012-09-28 23:21:46 -07001863 if (drvdata->pcsave_impl && boot_pcsave_enable)
1864 __etm_store_pcsave(drvdata, true);
1865
Pratik Patel7831c082011-06-08 21:44:37 -07001866 return 0;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001867err1:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001868 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001869err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001870 wake_lock_destroy(&drvdata->wake_lock);
1871 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001872 return ret;
1873}
1874
Pratik Patelf6fe9182012-03-20 14:04:18 -07001875static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001876{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001877 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1878
Pratik Patel938e1ff2012-09-28 23:21:46 -07001879 device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001880 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001881 wake_lock_destroy(&drvdata->wake_lock);
1882 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001883 return 0;
1884}
1885
Pratik Patel9eae4822012-05-14 17:34:53 -07001886static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001887 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001888 {}
1889};
1890
Pratik Patel492b3012012-03-06 14:22:30 -08001891static struct platform_driver etm_driver = {
1892 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001893 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001894 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001895 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001896 .owner = THIS_MODULE,
1897 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001898 },
1899};
1900
Pratik Patel492b3012012-03-06 14:22:30 -08001901int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001902{
Pratik Patel492b3012012-03-06 14:22:30 -08001903 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001904}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001905module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001906
Pratik Patelf6fe9182012-03-20 14:04:18 -07001907void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001908{
Pratik Patel492b3012012-03-06 14:22:30 -08001909 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001910}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001911module_exit(etm_exit);
1912
1913MODULE_LICENSE("GPL v2");
1914MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");