blob: 277776919a4b2c0134a1664643839c0496d81360 [file] [log] [blame]
Pushkar Joshi85688c62012-12-06 10:52:02 -08001/* Copyright (c) 2011-2013, 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 Patel0a10be22012-10-23 21:12:07 -070028#include <linux/spinlock.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070029#include <linux/clk.h>
Pratik Patel9dbfa372012-10-23 22:36:40 -070030#include <linux/cpu.h>
Pratik Patel5f6d1af2012-06-13 15:48:13 -070031#include <linux/of_coresight.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070032#include <linux/coresight.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080033#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080034#include <mach/socinfo.h>
Pratik Patel26477792012-09-07 01:35:36 -070035#include <mach/msm_memory_dump.h>
Pratik Patel7831c082011-06-08 21:44:37 -070036
Pratik Patel1746b8f2012-06-02 21:11:41 -070037#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070038
Pratik Patele6e41da2012-09-12 12:50:29 -070039#define etm_writel_mm(drvdata, val, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070040 __raw_writel((val), drvdata->base + off)
Pratik Patele6e41da2012-09-12 12:50:29 -070041#define etm_readl_mm(drvdata, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070042 __raw_readl(drvdata->base + off)
43
Pratik Patele6e41da2012-09-12 12:50:29 -070044#define etm_writel(drvdata, val, off) \
45({ \
46 if (cpu_is_krait_v3()) \
47 etm_writel_cp14(val, off); \
48 else \
49 etm_writel_mm(drvdata, val, off); \
50})
51#define etm_readl(drvdata, off) \
52({ \
53 uint32_t val; \
54 if (cpu_is_krait_v3()) \
55 val = etm_readl_cp14(off); \
56 else \
57 val = etm_readl_mm(drvdata, off); \
58 val; \
59})
60
Pratik Patel3b0ca882012-06-01 16:54:14 -070061#define ETM_LOCK(drvdata) \
62do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070063 /* recommended by spec to ensure ETM writes are committed prior
64 * to resuming execution
65 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070066 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070067 isb(); \
68 etm_writel_mm(drvdata, 0x0, CORESIGHT_LAR); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070069} while (0)
70#define ETM_UNLOCK(drvdata) \
71do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070072 etm_writel_mm(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
73 /* ensure unlock and any pending writes are committed prior to
74 * programming ETM registers
75 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070076 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070077 isb(); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070078} while (0)
79
Pratik Patel7831c082011-06-08 21:44:37 -070080/*
81 * Device registers:
82 * 0x000 - 0x2FC: Trace registers
83 * 0x300 - 0x314: Management registers
84 * 0x318 - 0xEFC: Trace registers
85 *
86 * Coresight registers
87 * 0xF00 - 0xF9C: Management registers
88 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
89 * Trace registers in PFTv1.1
90 * 0xFA8 - 0xFFC: Management registers
91 */
92
93/* Trace registers (0x000-0x2FC) */
Pushkar Joshi85688c62012-12-06 10:52:02 -080094#define ETMCR (0x000)
95#define ETMCCR (0x004)
96#define ETMTRIGGER (0x008)
97#define ETMASSICCTLR (0x00C)
98#define ETMSR (0x010)
99#define ETMSCR (0x014)
100#define ETMTSSCR (0x018)
101#define ETMTECR2 (0x01C)
102#define ETMTEEVR (0x020)
103#define ETMTECR1 (0x024)
104#define ETMFFLR (0x02C)
105#define ETMVDEVR (0x030)
106#define ETMVDCR1 (0x034)
107#define ETMVDCR3 (0x03C)
108#define ETMACVRn(n) (0x040 + (n * 4))
109#define ETMACTRn(n) (0x080 + (n * 4))
110#define ETMDCVRn(n) (0x0C0 + (n * 8))
111#define ETMDCMRn(n) (0x100 + (n * 8))
112#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
113#define ETMCNTENRn(n) (0x150 + (n * 4))
114#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
115#define ETMCNTVRn(n) (0x170 + (n * 4))
116#define ETMSQ12EVR (0x180)
117#define ETMSQ21EVR (0x184)
118#define ETMSQ23EVR (0x188)
119#define ETMSQ31EVR (0x18C)
120#define ETMSQ32EVR (0x190)
121#define ETMSQ13EVR (0x194)
122#define ETMSQR (0x19C)
123#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
124#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
125#define ETMCIDCMR (0x1BC)
126#define ETMIMPSPEC0 (0x1C0)
127#define ETMIMPSPEC1 (0x1C4)
128#define ETMIMPSPEC2 (0x1C8)
129#define ETMIMPSPEC3 (0x1CC)
130#define ETMIMPSPEC4 (0x1D0)
131#define ETMIMPSPEC5 (0x1D4)
132#define ETMIMPSPEC6 (0x1D8)
133#define ETMIMPSPEC7 (0x1DC)
134#define ETMSYNCFR (0x1E0)
135#define ETMIDR (0x1E4)
136#define ETMCCER (0x1E8)
137#define ETMEXTINSELR (0x1EC)
138#define ETMTESSEICR (0x1F0)
139#define ETMEIBCR (0x1F4)
140#define ETMTSEVR (0x1F8)
141#define ETMAUXCR (0x1FC)
142#define ETMTRACEIDR (0x200)
143#define ETMIDR2 (0x208)
144#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700145/* Management registers (0x300-0x314) */
Pushkar Joshi85688c62012-12-06 10:52:02 -0800146#define ETMOSLAR (0x300)
147#define ETMOSLSR (0x304)
148#define ETMOSSRR (0x308)
149#define ETMPDCR (0x310)
150#define ETMPDSR (0x314)
Pratik Patel7831c082011-06-08 21:44:37 -0700151
Pushkar Joshi85688c62012-12-06 10:52:02 -0800152#define ETM_MAX_ADDR_CMP (16)
153#define ETM_MAX_CNTR (4)
154#define ETM_MAX_CTXID_CMP (3)
Pratik Patel61de7302012-03-07 12:06:10 -0800155
Pushkar Joshi85688c62012-12-06 10:52:02 -0800156#define ETM_MODE_EXCLUDE BIT(0)
157#define ETM_MODE_CYCACC BIT(1)
158#define ETM_MODE_STALL BIT(2)
159#define ETM_MODE_TIMESTAMP BIT(3)
160#define ETM_MODE_CTXID BIT(4)
161#define ETM_MODE_DATA_TRACE_VAL BIT(5)
162#define ETM_MODE_DATA_TRACE_ADDR BIT(6)
163#define ETM_MODE_ALL (0x7F)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800164
Pushkar Joshi85688c62012-12-06 10:52:02 -0800165#define ETM_DATACMP_ENABLE (0x2)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800166
Pushkar Joshi85688c62012-12-06 10:52:02 -0800167#define ETM_EVENT_MASK (0x1FFFF)
168#define ETM_SYNC_MASK (0xFFF)
169#define ETM_ALL_MASK (0xFFFFFFFF)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800170
Pushkar Joshi85688c62012-12-06 10:52:02 -0800171#define ETM_SEQ_STATE_MAX_VAL (0x2)
172
173#define ETM_REG_DUMP_VER_OFF (4)
174#define ETM_REG_DUMP_VER (1)
Pratik Patel26477792012-09-07 01:35:36 -0700175
Pratik Patel36cc4482013-02-09 23:02:47 -0800176#define CPMR_ETMCLKEN (8)
177
Pratik Patel3b0ca882012-06-01 16:54:14 -0700178enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800179 ETM_ADDR_TYPE_NONE,
180 ETM_ADDR_TYPE_SINGLE,
181 ETM_ADDR_TYPE_RANGE,
182 ETM_ADDR_TYPE_START,
183 ETM_ADDR_TYPE_STOP,
184};
185
Pratik Patel61e91702013-01-27 20:30:42 -0800186#ifdef CONFIG_CORESIGHT_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700187static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800188#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700189static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800190#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700191module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700192 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700193);
194
Pratik Patel61e91702013-01-27 20:30:42 -0800195#ifdef CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE
Pratik Patel938e1ff2012-09-28 23:21:46 -0700196static int boot_pcsave_enable = 1;
197#else
198static int boot_pcsave_enable;
199#endif
200module_param_named(
201 boot_pcsave_enable, boot_pcsave_enable, int, S_IRUGO
202);
203
Pratik Patel16aefdb2012-05-30 10:41:23 -0700204struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700205 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700206 struct device *dev;
207 struct coresight_device *csdev;
208 struct clk *clk;
Pratik Patel0a10be22012-10-23 21:12:07 -0700209 spinlock_t spinlock;
Pratik Patel7831c082011-06-08 21:44:37 -0700210 struct wake_lock wake_lock;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700211 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800212 uint8_t arch;
Pratik Patelf3238df2012-10-19 16:19:12 -0700213 bool enable;
Pratik Patelb7fd0602012-11-28 15:29:02 -0800214 bool sticky_enable;
215 bool boot_enable;
Pratik Patel97a08f32012-10-22 11:47:41 -0700216 bool os_unlock;
Pratik Patel61de7302012-03-07 12:06:10 -0800217 uint8_t nr_addr_cmp;
218 uint8_t nr_cntr;
219 uint8_t nr_ext_inp;
220 uint8_t nr_ext_out;
221 uint8_t nr_ctxid_cmp;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800222 uint8_t nr_data_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800223 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800224 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800225 uint32_t ctrl;
226 uint32_t trigger_event;
227 uint32_t startstop_ctrl;
228 uint32_t enable_event;
229 uint32_t enable_ctrl1;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800230 uint32_t enable_ctrl2;
Pratik Patel61de7302012-03-07 12:06:10 -0800231 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800232 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800233 uint32_t addr_val[ETM_MAX_ADDR_CMP];
234 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800235 uint32_t addr_type[ETM_MAX_ADDR_CMP];
Pushkar Joshi85688c62012-12-06 10:52:02 -0800236 bool data_trace_support;
237 uint32_t data_val[ETM_MAX_ADDR_CMP];
238 uint32_t data_mask[ETM_MAX_ADDR_CMP];
239 uint32_t viewdata_event;
240 uint32_t viewdata_ctrl1;
241 uint32_t viewdata_ctrl3;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800242 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800243 uint32_t cntr_rld_val[ETM_MAX_CNTR];
244 uint32_t cntr_event[ETM_MAX_CNTR];
245 uint32_t cntr_rld_event[ETM_MAX_CNTR];
246 uint32_t cntr_val[ETM_MAX_CNTR];
247 uint32_t seq_12_event;
248 uint32_t seq_21_event;
249 uint32_t seq_23_event;
250 uint32_t seq_31_event;
251 uint32_t seq_32_event;
252 uint32_t seq_13_event;
253 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800254 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800255 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
256 uint32_t ctxid_mask;
257 uint32_t sync_freq;
258 uint32_t timestamp_event;
Pratik Patel938e1ff2012-09-28 23:21:46 -0700259 bool pcsave_impl;
260 bool pcsave_enable;
Pratik Patelcd2452e2012-11-15 09:57:29 -0800261 bool pcsave_sticky_enable;
262 bool pcsave_boot_enable;
Pratik Pateldbb352b2013-01-22 18:23:57 -0800263 bool round_robin;
Pratik Patel7831c082011-06-08 21:44:37 -0700264};
265
Pratik Patel97a08f32012-10-22 11:47:41 -0700266static struct etm_drvdata *etmdrvdata[NR_CPUS];
267
Pushkar Joshicba120a2013-03-05 18:37:39 -0800268static bool etm_os_lock_present(struct etm_drvdata *drvdata)
269{
270 uint32_t etmoslsr;
271
272 etmoslsr = etm_readl(drvdata, ETMOSLSR);
273 if (!BVAL(etmoslsr, 0) && !BVAL(etmoslsr, 3))
274 return false;
275 return true;
276}
277
Pratik Patel97a08f32012-10-22 11:47:41 -0700278/*
279 * Memory mapped writes to clear os lock are not supported on Krait v1, v2
280 * and OS lock must be unlocked before any memory mapped access, otherwise
281 * memory mapped reads/writes will be invalid.
282 */
283static void etm_os_unlock(void *info)
284{
Pushkar Joshicba120a2013-03-05 18:37:39 -0800285 struct etm_drvdata *drvdata = (struct etm_drvdata *) info;
286
287 ETM_UNLOCK(drvdata);
Pushkar Joshi85688c62012-12-06 10:52:02 -0800288 if (cpu_is_krait()) {
289 etm_writel_cp14(0x0, ETMOSLAR);
290 isb();
Pushkar Joshicba120a2013-03-05 18:37:39 -0800291 } else if (etm_os_lock_present(drvdata)) {
292 etm_writel(drvdata, 0x0, ETMOSLAR);
293 mb();
Pushkar Joshi85688c62012-12-06 10:52:02 -0800294 }
Pushkar Joshicba120a2013-03-05 18:37:39 -0800295 ETM_LOCK(drvdata);
Pratik Patel97a08f32012-10-22 11:47:41 -0700296}
Pratik Patelc14b4df2012-09-05 18:07:59 -0700297
Pratik Pateld1d65c92012-09-25 23:37:43 -0700298/*
299 * ETM clock is derived from the processor clock and gets enabled on a
300 * logical OR of below items on Krait (v2 onwards):
Pratik Patel17f3b822011-11-21 12:41:47 -0800301 * 1.CPMR[ETMCLKEN] is 1
302 * 2.ETMCR[PD] is 0
303 * 3.ETMPDCR[PU] is 1
304 * 4.Reset is asserted (core or debug)
305 * 5.APB memory mapped requests (eg. EDAP access)
306 *
307 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
308 * enables
309 *
Pratik Pateld1d65c92012-09-25 23:37:43 -0700310 * We rely on 5. to be able to access ETMCR/ETMPDCR and then use 2./3. above
311 * for ETM clock vote in the driver and the save-restore code uses 1. above
Pratik Patel17f3b822011-11-21 12:41:47 -0800312 * for its vote
313 */
Pratik Pateld1d65c92012-09-25 23:37:43 -0700314static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
315{
316 uint32_t etmcr;
317
318 /* ensure pending cp14 accesses complete before setting pwrdwn */
319 mb();
320 isb();
321 etmcr = etm_readl(drvdata, ETMCR);
322 etmcr |= BIT(0);
323 etm_writel(drvdata, etmcr, ETMCR);
324}
325
326static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
327{
328 uint32_t etmcr;
329
330 etmcr = etm_readl(drvdata, ETMCR);
331 etmcr &= ~BIT(0);
332 etm_writel(drvdata, etmcr, ETMCR);
333 /* ensure pwrup completes before subsequent cp14 accesses */
334 mb();
335 isb();
336}
337
Pratik Patelef6da292012-09-17 17:37:19 -0700338static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700339{
Pratik Patel36cc4482013-02-09 23:02:47 -0800340 uint32_t cpmr;
Pratik Patelef6da292012-09-17 17:37:19 -0700341 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700342
Pratik Patel36cc4482013-02-09 23:02:47 -0800343 /* For Krait, use cp15 CPMR_ETMCLKEN instead of ETMPDCR since ETMPDCR
344 * is not supported for this purpose on Krait v4.
345 */
346 if (cpu_is_krait()) {
347 asm volatile("mrc p15, 7, %0, c15, c0, 5" : "=r" (cpmr));
348 cpmr |= CPMR_ETMCLKEN;
349 asm volatile("mcr p15, 7, %0, c15, c0, 5" : : "r" (cpmr));
350 } else {
351 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
352 etmpdcr |= BIT(3);
353 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
354 }
Pratik Patele6e41da2012-09-12 12:50:29 -0700355 /* ensure pwrup completes before subsequent cp14 accesses */
356 mb();
357 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700358}
359
Pratik Patelef6da292012-09-17 17:37:19 -0700360static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700361{
Pratik Patel36cc4482013-02-09 23:02:47 -0800362 uint32_t cpmr;
Pratik Patelef6da292012-09-17 17:37:19 -0700363 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700364
Pratik Patele6e41da2012-09-12 12:50:29 -0700365 /* ensure pending cp14 accesses complete before clearing pwrup */
366 mb();
367 isb();
Pratik Patel36cc4482013-02-09 23:02:47 -0800368 /* For Krait, use cp15 CPMR_ETMCLKEN instead of ETMPDCR since ETMPDCR
369 * is not supported for this purpose on Krait v4.
370 */
371 if (cpu_is_krait()) {
372 asm volatile("mrc p15, 7, %0, c15, c0, 5" : "=r" (cpmr));
373 cpmr &= ~CPMR_ETMCLKEN;
374 asm volatile("mcr p15, 7, %0, c15, c0, 5" : : "r" (cpmr));
375 } else {
376 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
377 etmpdcr &= ~BIT(3);
378 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
379 }
Pratik Patel7831c082011-06-08 21:44:37 -0700380}
381
Pratik Patel3b0ca882012-06-01 16:54:14 -0700382static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700383{
384 uint32_t etmcr;
385 int count;
386
Pratik Patel3b0ca882012-06-01 16:54:14 -0700387 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700388 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700389 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700390 /* recommended by spec for cp14 accesses to ensure etmcr write is
391 * complete before polling etmsr
392 */
393 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700394 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700395 && count > 0; count--)
396 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800397 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700398 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700399}
400
Pratik Patel3b0ca882012-06-01 16:54:14 -0700401static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700402{
403 uint32_t etmcr;
404 int count;
405
Pratik Patel3b0ca882012-06-01 16:54:14 -0700406 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700407 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700408 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700409 /* recommended by spec for cp14 accesses to ensure etmcr write is
410 * complete before polling etmsr
411 */
412 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700413 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700414 && count > 0; count--)
415 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800416 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700417 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700418}
419
Pratik Patel938e1ff2012-09-28 23:21:46 -0700420static void etm_enable_pcsave(void *info)
421{
422 struct etm_drvdata *drvdata = info;
423
424 ETM_UNLOCK(drvdata);
425
Pratik Patel938e1ff2012-09-28 23:21:46 -0700426 /*
427 * ETMPDCR is only accessible via memory mapped interface and so use
428 * it first to enable power/clock to allow subsequent cp14 accesses.
429 */
430 etm_set_pwrup(drvdata);
431 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800432 etm_clr_pwrup(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700433
434 ETM_LOCK(drvdata);
435}
436
437static void etm_disable_pcsave(void *info)
438{
439 struct etm_drvdata *drvdata = info;
440
441 ETM_UNLOCK(drvdata);
442
Pratik Patelf95c5402012-11-05 18:21:08 -0800443 if (!drvdata->enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700444 etm_set_pwrdwn(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700445
446 ETM_LOCK(drvdata);
447}
448
Pushkar Joshi85688c62012-12-06 10:52:02 -0800449static bool etm_version_gte(uint8_t arch, uint8_t base_arch)
450{
451 if (arch >= base_arch && ((arch & PFT_ARCH_MAJOR) != PFT_ARCH_MAJOR))
452 return true;
453 else
454 return false;
455}
456
Pratik Patel66e1a412012-09-06 11:07:06 -0700457static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700458{
Pratik Patel17f3b822011-11-21 12:41:47 -0800459 int i;
Pratik Pateld1d65c92012-09-25 23:37:43 -0700460 uint32_t etmcr;
Pratik Patel66e1a412012-09-06 11:07:06 -0700461 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700462
Pratik Patel3b0ca882012-06-01 16:54:14 -0700463 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700464 /*
465 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
466 * memory mapped interface and so use it first to enable power/clock
467 * to allow subsequent cp14 accesses.
468 */
Pratik Patelef6da292012-09-17 17:37:19 -0700469 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -0700470 /*
471 * Clear power down bit since when this bit is set writes to
Pratik Patelf3238df2012-10-19 16:19:12 -0700472 * certain registers might be ignored. This is also a pre-requisite
473 * for trace enable.
Pratik Pateld1d65c92012-09-25 23:37:43 -0700474 */
475 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800476 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700477 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700478
Pratik Pateld1d65c92012-09-25 23:37:43 -0700479 etmcr = etm_readl(drvdata, ETMCR);
480 etmcr &= (BIT(10) | BIT(0));
481 etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700482 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
483 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
Pushkar Joshi85688c62012-12-06 10:52:02 -0800484 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
485 etm_writel(drvdata, drvdata->enable_ctrl2, ETMTECR2);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700486 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
487 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
488 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pushkar Joshi85688c62012-12-06 10:52:02 -0800489 if (drvdata->data_trace_support == true) {
490 etm_writel(drvdata, drvdata->viewdata_event, ETMVDEVR);
491 etm_writel(drvdata, drvdata->viewdata_ctrl1, ETMVDCR1);
492 etm_writel(drvdata, drvdata->viewdata_ctrl3, ETMVDCR3);
493 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700494 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700495 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
496 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700497 }
Pushkar Joshi85688c62012-12-06 10:52:02 -0800498 for (i = 0; i < drvdata->nr_data_cmp; i++) {
499 etm_writel(drvdata, drvdata->data_val[i], ETMDCVRn(i));
500 etm_writel(drvdata, drvdata->data_mask[i], ETMDCMRn(i));
501 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700502 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700503 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
504 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
505 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700506 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700507 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800508 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700509 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
510 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
511 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
512 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
513 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
514 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
515 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700516 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700517 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700518 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700519 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
520 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
521 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
522 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
523 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
524 etm_writel(drvdata, 0x00000000, ETMAUXCR);
525 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
526 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800527
Pratik Patel3b0ca882012-06-01 16:54:14 -0700528 etm_clr_prog(drvdata);
529 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700530
531 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700532}
533
Pratik Patel3b0ca882012-06-01 16:54:14 -0700534static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700535{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700536 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
537 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800538
Pratik Patel16aefdb2012-05-30 10:41:23 -0700539 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700540
Pratik Patel16aefdb2012-05-30 10:41:23 -0700541 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700542 if (ret)
543 goto err_clk;
544
Pratik Patel0a10be22012-10-23 21:12:07 -0700545 spin_lock(&drvdata->spinlock);
546
Pratik Patelf3238df2012-10-19 16:19:12 -0700547 /*
548 * Executing __etm_enable on the cpu whose ETM is being enabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700549 * ensures that register writes occur when cpu is powered.
550 */
Pratik Patel97a08f32012-10-22 11:47:41 -0700551 ret = smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
552 if (ret)
553 goto err;
Pratik Patelf3238df2012-10-19 16:19:12 -0700554 drvdata->enable = true;
Pratik Patelb7fd0602012-11-28 15:29:02 -0800555 drvdata->sticky_enable = true;
Pratik Patel0a10be22012-10-23 21:12:07 -0700556
557 spin_unlock(&drvdata->spinlock);
Pratik Patel7831c082011-06-08 21:44:37 -0700558
Pratik Patel16aefdb2012-05-30 10:41:23 -0700559 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700560
Pratik Patel16aefdb2012-05-30 10:41:23 -0700561 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700562 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -0700563err:
564 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700565 clk_disable_unprepare(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700566err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700567 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800568 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700569}
570
Pratik Patel66e1a412012-09-06 11:07:06 -0700571static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700572{
Pratik Patel66e1a412012-09-06 11:07:06 -0700573 struct etm_drvdata *drvdata = info;
574
Pratik Patel3b0ca882012-06-01 16:54:14 -0700575 ETM_UNLOCK(drvdata);
576 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700577
Pratik Patel17f3b822011-11-21 12:41:47 -0800578 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700579 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700580
Pratik Patelf95c5402012-11-05 18:21:08 -0800581 if (!drvdata->pcsave_enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700582 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700583 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700584
585 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700586}
587
Pratik Patel3b0ca882012-06-01 16:54:14 -0700588static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700589{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700590 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800591
Pratik Patel16aefdb2012-05-30 10:41:23 -0700592 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700593
Pratik Patelb3354262012-11-30 16:15:46 -0800594 /*
595 * Taking hotplug lock here protects from clocks getting disabled
596 * with tracing being left on (crash scenario) if user disable occurs
597 * after cpu online mask indicates the cpu is offline but before the
598 * DYING hotplug callback is serviced by the ETM driver.
599 */
Pratik Patel97a08f32012-10-22 11:47:41 -0700600 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -0700601 spin_lock(&drvdata->spinlock);
602
Pratik Patelf3238df2012-10-19 16:19:12 -0700603 /*
604 * Executing __etm_disable on the cpu whose ETM is being disabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700605 * ensures that register writes occur when cpu is powered.
606 */
607 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patelf3238df2012-10-19 16:19:12 -0700608 drvdata->enable = false;
Pratik Patel0a10be22012-10-23 21:12:07 -0700609
610 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700611 put_online_cpus();
Pratik Patel7831c082011-06-08 21:44:37 -0700612
Pratik Patel16aefdb2012-05-30 10:41:23 -0700613 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700614
Pratik Patel16aefdb2012-05-30 10:41:23 -0700615 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700616
Pratik Patel16aefdb2012-05-30 10:41:23 -0700617 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700618}
619
Pratik Patel3b0ca882012-06-01 16:54:14 -0700620static const struct coresight_ops_source etm_source_ops = {
621 .enable = etm_enable,
622 .disable = etm_disable,
623};
Pratik Patel17f3b822011-11-21 12:41:47 -0800624
Pratik Patel3b0ca882012-06-01 16:54:14 -0700625static const struct coresight_ops etm_cs_ops = {
626 .source_ops = &etm_source_ops,
627};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800628
Pratik Patela9c0e062012-05-28 13:45:35 -0700629static ssize_t etm_show_nr_addr_cmp(struct device *dev,
630 struct device_attribute *attr, char *buf)
631{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700632 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700633 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700634
Pratik Patela9c0e062012-05-28 13:45:35 -0700635 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
636}
637static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
638
639static ssize_t etm_show_nr_cntr(struct device *dev,
640 struct device_attribute *attr, char *buf)
641{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700642 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700643 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700644
Pratik Patela9c0e062012-05-28 13:45:35 -0700645 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
646}
647static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
648
649static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
650 struct device_attribute *attr, char *buf)
651{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700652 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700653 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700654
Pratik Patela9c0e062012-05-28 13:45:35 -0700655 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
656}
657static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
658
659static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
660 char *buf)
661{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700662 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700663 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700664
Pratik Patela9c0e062012-05-28 13:45:35 -0700665 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
666}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800667
Pratik Pateld30deda2012-02-01 14:40:55 -0800668/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700669static ssize_t etm_store_reset(struct device *dev,
670 struct device_attribute *attr, const char *buf,
671 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800672{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700673 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800674 int i;
675 unsigned long val;
676
677 if (sscanf(buf, "%lx", &val) != 1)
678 return -EINVAL;
679
Pratik Patel0a10be22012-10-23 21:12:07 -0700680 spin_lock(&drvdata->spinlock);
Pratik Pateld30deda2012-02-01 14:40:55 -0800681 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700682 drvdata->mode = ETM_MODE_EXCLUDE;
683 drvdata->ctrl = 0x0;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800684 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
685 drvdata->ctrl |= BIT(11);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800686 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700687 drvdata->mode |= ETM_MODE_CYCACC;
688 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800689 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700690 drvdata->trigger_event = 0x406F;
691 drvdata->startstop_ctrl = 0x0;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800692 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
693 drvdata->enable_ctrl2 = 0x0;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700694 drvdata->enable_event = 0x6F;
695 drvdata->enable_ctrl1 = 0x1000000;
696 drvdata->fifofull_level = 0x28;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800697 if (drvdata->data_trace_support == true) {
698 drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
699 ETM_MODE_DATA_TRACE_ADDR);
700 drvdata->ctrl |= BIT(2) | BIT(3);
701 drvdata->viewdata_event = 0x6F;
702 drvdata->viewdata_ctrl1 = 0x0;
703 drvdata->viewdata_ctrl3 = 0x10000;
704 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700705 drvdata->addr_idx = 0x0;
706 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
707 drvdata->addr_val[i] = 0x0;
708 drvdata->addr_acctype[i] = 0x0;
709 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800710 }
Pushkar Joshi85688c62012-12-06 10:52:02 -0800711 for (i = 0; i < drvdata->nr_data_cmp; i++) {
712 drvdata->data_val[i] = 0;
713 drvdata->data_mask[i] = ~(0);
714 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700715 drvdata->cntr_idx = 0x0;
716 for (i = 0; i < drvdata->nr_cntr; i++) {
717 drvdata->cntr_rld_val[i] = 0x0;
718 drvdata->cntr_event[i] = 0x406F;
719 drvdata->cntr_rld_event[i] = 0x406F;
720 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800721 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700722 drvdata->seq_12_event = 0x406F;
723 drvdata->seq_21_event = 0x406F;
724 drvdata->seq_23_event = 0x406F;
725 drvdata->seq_31_event = 0x406F;
726 drvdata->seq_32_event = 0x406F;
727 drvdata->seq_13_event = 0x406F;
728 drvdata->seq_curr_state = 0x0;
729 drvdata->ctxid_idx = 0x0;
730 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
731 drvdata->ctxid_val[i] = 0x0;
732 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700733 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
734 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
735 drvdata->sync_freq = 0x100;
736 else
737 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700738 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800739 }
Pratik Patel0a10be22012-10-23 21:12:07 -0700740 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700741 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800742}
Pratik Patela9c0e062012-05-28 13:45:35 -0700743static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800744
Pratik Patela9c0e062012-05-28 13:45:35 -0700745static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
746 char *buf)
747{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700748 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700749 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700750
Pratik Patela9c0e062012-05-28 13:45:35 -0700751 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
752}
753
754static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
755 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800756{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700757 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800758 unsigned long val;
759
760 if (sscanf(buf, "%lx", &val) != 1)
761 return -EINVAL;
762
Pratik Patel0a10be22012-10-23 21:12:07 -0700763 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700764 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800765
Pratik Patel16aefdb2012-05-30 10:41:23 -0700766 if (drvdata->mode & ETM_MODE_EXCLUDE)
767 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800768 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700769 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800770
Pratik Patel16aefdb2012-05-30 10:41:23 -0700771 if (drvdata->mode & ETM_MODE_CYCACC)
772 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800773 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700774 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800775
Pratik Patel16aefdb2012-05-30 10:41:23 -0700776 if (drvdata->mode & ETM_MODE_STALL)
777 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800778 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700779 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800780
Pratik Patel16aefdb2012-05-30 10:41:23 -0700781 if (drvdata->mode & ETM_MODE_TIMESTAMP)
782 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800783 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700784 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700785
Pratik Patel16aefdb2012-05-30 10:41:23 -0700786 if (drvdata->mode & ETM_MODE_CTXID)
787 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800788 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700789 drvdata->ctrl &= ~(BIT(14) | BIT(15));
Pushkar Joshi85688c62012-12-06 10:52:02 -0800790 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
791 if (drvdata->mode & ETM_MODE_DATA_TRACE_VAL)
792 drvdata->ctrl |= BIT(2);
793 else
794 drvdata->ctrl &= ~(BIT(2));
795
796 if (drvdata->mode & ETM_MODE_DATA_TRACE_ADDR)
797 drvdata->ctrl |= (BIT(3));
798 else
799 drvdata->ctrl &= ~(BIT(3));
800 }
Pratik Patel0a10be22012-10-23 21:12:07 -0700801 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800802
Pratik Patela9c0e062012-05-28 13:45:35 -0700803 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800804}
Pratik Patela9c0e062012-05-28 13:45:35 -0700805static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800806
Pratik Patela9c0e062012-05-28 13:45:35 -0700807static ssize_t etm_show_trigger_event(struct device *dev,
808 struct device_attribute *attr, char *buf)
809{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700810 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700811 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700812
Pratik Patela9c0e062012-05-28 13:45:35 -0700813 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
814}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800815
Pratik Patela9c0e062012-05-28 13:45:35 -0700816static ssize_t etm_store_trigger_event(struct device *dev,
817 struct device_attribute *attr,
818 const char *buf, size_t size)
819{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700820 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700821 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800822
Pratik Patela9c0e062012-05-28 13:45:35 -0700823 if (sscanf(buf, "%lx", &val) != 1)
824 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800825
Pratik Patel16aefdb2012-05-30 10:41:23 -0700826 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700827 return size;
828}
829static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
830 etm_store_trigger_event);
831
832static ssize_t etm_show_enable_event(struct device *dev,
833 struct device_attribute *attr, char *buf)
834{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700835 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700836 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700837
Pratik Patela9c0e062012-05-28 13:45:35 -0700838 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
839}
840
841static ssize_t etm_store_enable_event(struct device *dev,
842 struct device_attribute *attr,
843 const char *buf, size_t size)
844{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700845 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700846 unsigned long val;
847
848 if (sscanf(buf, "%lx", &val) != 1)
849 return -EINVAL;
850
Pratik Patel16aefdb2012-05-30 10:41:23 -0700851 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700852 return size;
853}
854static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
855 etm_store_enable_event);
856
857static ssize_t etm_show_fifofull_level(struct device *dev,
858 struct device_attribute *attr, char *buf)
859{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700860 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700861 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700862
Pratik Patela9c0e062012-05-28 13:45:35 -0700863 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
864}
865
866static ssize_t etm_store_fifofull_level(struct device *dev,
867 struct device_attribute *attr,
868 const char *buf, size_t size)
869{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700870 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700871 unsigned long val;
872
873 if (sscanf(buf, "%lx", &val) != 1)
874 return -EINVAL;
875
Pratik Patel16aefdb2012-05-30 10:41:23 -0700876 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700877 return size;
878}
879static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
880 etm_store_fifofull_level);
881
882static ssize_t etm_show_addr_idx(struct device *dev,
883 struct device_attribute *attr, char *buf)
884{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700885 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700886 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700887
Pratik Patela9c0e062012-05-28 13:45:35 -0700888 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
889}
890
891static ssize_t etm_store_addr_idx(struct device *dev,
892 struct device_attribute *attr,
893 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800894{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700895 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800896 unsigned long val;
897
898 if (sscanf(buf, "%lx", &val) != 1)
899 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700900 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800901 return -EINVAL;
902
Pratik Patel0a10be22012-10-23 21:12:07 -0700903 /*
904 * Use spinlock to ensure index doesn't change while it gets
905 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -0800906 */
Pratik Patel0a10be22012-10-23 21:12:07 -0700907 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700908 drvdata->addr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -0700909 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700910 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800911}
Pratik Patela9c0e062012-05-28 13:45:35 -0700912static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
913 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800914
Pratik Patela9c0e062012-05-28 13:45:35 -0700915static ssize_t etm_show_addr_single(struct device *dev,
916 struct device_attribute *attr, char *buf)
917{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700918 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700919 unsigned long val;
920 uint8_t idx;
921
Pratik Patel0a10be22012-10-23 21:12:07 -0700922 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700923 idx = drvdata->addr_idx;
924 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
925 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700926 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700927 return -EPERM;
928 }
929
Pratik Patel16aefdb2012-05-30 10:41:23 -0700930 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700931 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700932 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
933}
934
935static ssize_t etm_store_addr_single(struct device *dev,
936 struct device_attribute *attr,
937 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800938{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700939 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800940 unsigned long val;
941 uint8_t idx;
942
943 if (sscanf(buf, "%lx", &val) != 1)
944 return -EINVAL;
945
Pratik Patel0a10be22012-10-23 21:12:07 -0700946 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700947 idx = drvdata->addr_idx;
948 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
949 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700950 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800951 return -EPERM;
952 }
953
Pratik Patel16aefdb2012-05-30 10:41:23 -0700954 drvdata->addr_val[idx] = val;
955 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800956 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
957 drvdata->enable_ctrl2 |= (1 << idx);
Pratik Patel0a10be22012-10-23 21:12:07 -0700958 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700959 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800960}
Pratik Patela9c0e062012-05-28 13:45:35 -0700961static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
962 etm_store_addr_single);
963
964static ssize_t etm_show_addr_range(struct device *dev,
965 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800966{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700967 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700968 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800969 uint8_t idx;
970
Pratik Patel0a10be22012-10-23 21:12:07 -0700971 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700972 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700973 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700974 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700975 return -EPERM;
976 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700977 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
978 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
979 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
980 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700981 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800982 return -EPERM;
983 }
984
Pratik Patel16aefdb2012-05-30 10:41:23 -0700985 val1 = drvdata->addr_val[idx];
986 val2 = drvdata->addr_val[idx + 1];
Pratik Patel0a10be22012-10-23 21:12:07 -0700987 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700988 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800989}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800990
Pratik Patela9c0e062012-05-28 13:45:35 -0700991static ssize_t etm_store_addr_range(struct device *dev,
992 struct device_attribute *attr,
993 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800994{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700995 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800996 unsigned long val1, val2;
997 uint8_t idx;
998
999 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
1000 return -EINVAL;
1001 /* lower address comparator cannot have a higher address value */
1002 if (val1 > val2)
1003 return -EINVAL;
1004
Pratik Patel0a10be22012-10-23 21:12:07 -07001005 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001006 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001007 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001008 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001009 return -EPERM;
1010 }
Pratik Patel16aefdb2012-05-30 10:41:23 -07001011 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
1012 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
1013 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
1014 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001015 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001016 return -EPERM;
1017 }
1018
Pratik Patel16aefdb2012-05-30 10:41:23 -07001019 drvdata->addr_val[idx] = val1;
1020 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
1021 drvdata->addr_val[idx + 1] = val2;
1022 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
1023 drvdata->enable_ctrl1 |= (1 << (idx/2));
Pratik Patel0a10be22012-10-23 21:12:07 -07001024 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001025 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001026}
Pratik Patela9c0e062012-05-28 13:45:35 -07001027static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
1028 etm_store_addr_range);
1029
1030static ssize_t etm_show_addr_start(struct device *dev,
1031 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001032{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001033 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001034 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001035 uint8_t idx;
1036
Pratik Patel0a10be22012-10-23 21:12:07 -07001037 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001038 idx = drvdata->addr_idx;
1039 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1040 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001041 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001042 return -EPERM;
1043 }
1044
Pratik Patel16aefdb2012-05-30 10:41:23 -07001045 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001046 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001047 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001048}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001049
Pratik Patela9c0e062012-05-28 13:45:35 -07001050static ssize_t etm_store_addr_start(struct device *dev,
1051 struct device_attribute *attr,
1052 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001053{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001054 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001055 unsigned long val;
1056 uint8_t idx;
1057
1058 if (sscanf(buf, "%lx", &val) != 1)
1059 return -EINVAL;
1060
Pratik Patel0a10be22012-10-23 21:12:07 -07001061 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001062 idx = drvdata->addr_idx;
1063 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1064 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001065 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001066 return -EPERM;
1067 }
1068
Pratik Patel16aefdb2012-05-30 10:41:23 -07001069 drvdata->addr_val[idx] = val;
1070 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
1071 drvdata->startstop_ctrl |= (1 << idx);
1072 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -07001073 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001074 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001075}
Pratik Patela9c0e062012-05-28 13:45:35 -07001076static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
1077 etm_store_addr_start);
1078
1079static ssize_t etm_show_addr_stop(struct device *dev,
1080 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001081{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001082 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001083 unsigned long val;
1084 uint8_t idx;
1085
Pratik Patel0a10be22012-10-23 21:12:07 -07001086 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001087 idx = drvdata->addr_idx;
1088 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1089 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001090 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001091 return -EPERM;
1092 }
1093
Pratik Patel16aefdb2012-05-30 10:41:23 -07001094 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001095 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001096 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1097}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001098
Pratik Patela9c0e062012-05-28 13:45:35 -07001099static ssize_t etm_store_addr_stop(struct device *dev,
1100 struct device_attribute *attr,
1101 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001102{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001103 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001104 unsigned long val;
1105 uint8_t idx;
1106
1107 if (sscanf(buf, "%lx", &val) != 1)
1108 return -EINVAL;
1109
Pratik Patel0a10be22012-10-23 21:12:07 -07001110 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001111 idx = drvdata->addr_idx;
1112 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1113 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001114 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001115 return -EPERM;
1116 }
1117
Pratik Patel16aefdb2012-05-30 10:41:23 -07001118 drvdata->addr_val[idx] = val;
1119 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
1120 drvdata->startstop_ctrl |= (1 << (idx + 16));
1121 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -07001122 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001123 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001124}
Pratik Patela9c0e062012-05-28 13:45:35 -07001125static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
1126 etm_store_addr_stop);
1127
1128static ssize_t etm_show_addr_acctype(struct device *dev,
1129 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001130{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001131 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001132 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001133
Pratik Patel0a10be22012-10-23 21:12:07 -07001134 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001135 val = drvdata->addr_acctype[drvdata->addr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001136 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001137 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1138}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001139
Pratik Patela9c0e062012-05-28 13:45:35 -07001140static ssize_t etm_store_addr_acctype(struct device *dev,
1141 struct device_attribute *attr,
1142 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001143{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001144 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001145 unsigned long val;
1146
1147 if (sscanf(buf, "%lx", &val) != 1)
1148 return -EINVAL;
1149
Pratik Patel0a10be22012-10-23 21:12:07 -07001150 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001151 drvdata->addr_acctype[drvdata->addr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001152 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001153 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001154}
Pratik Patela9c0e062012-05-28 13:45:35 -07001155static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
1156 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001157
Pushkar Joshi85688c62012-12-06 10:52:02 -08001158static ssize_t etm_show_data_val(struct device *dev,
1159 struct device_attribute *attr, char *buf)
1160{
1161 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1162 unsigned long val;
1163 uint8_t idx;
1164
1165 spin_lock(&drvdata->spinlock);
1166 idx = drvdata->addr_idx;
1167 if (idx % 2 != 0) {
1168 spin_unlock(&drvdata->spinlock);
1169 return -EPERM;
1170 }
1171 idx = idx >> 1;
1172 if (idx >= drvdata->nr_data_cmp) {
1173 spin_unlock(&drvdata->spinlock);
1174 return -EPERM;
1175 }
1176
1177 val = drvdata->data_val[idx];
1178 spin_unlock(&drvdata->spinlock);
1179 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1180}
1181
1182static ssize_t etm_store_data_val(struct device *dev,
1183 struct device_attribute *attr,
1184 const char *buf, size_t size)
1185{
1186 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1187 unsigned long val;
1188 uint8_t idx, data_idx;
1189
1190 if (sscanf(buf, "%lx", &val) != 1)
1191 return -EINVAL;
1192
1193 spin_lock(&drvdata->spinlock);
1194 idx = drvdata->addr_idx;
1195 /* Adjust index to use the correct data comparator */
1196 data_idx = idx >> 1;
1197 /* Only idx = 0, 2, 4, 6... are valid */
1198 if (idx % 2 != 0) {
1199 spin_unlock(&drvdata->spinlock);
1200 return -EPERM;
1201 }
1202 if (data_idx >= drvdata->nr_data_cmp) {
1203 spin_unlock(&drvdata->spinlock);
1204 return -EPERM;
1205 }
1206 if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
1207 spin_unlock(&drvdata->spinlock);
1208 return -EPERM;
1209 }
1210 if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
1211 if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
1212 spin_unlock(&drvdata->spinlock);
1213 return -EPERM;
1214 }
1215 }
1216
1217 drvdata->data_val[data_idx] = val;
1218 spin_unlock(&drvdata->spinlock);
1219 return size;
1220}
1221static DEVICE_ATTR(data_val, S_IRUGO | S_IWUSR, etm_show_data_val,
1222 etm_store_data_val);
1223
1224static ssize_t etm_show_data_mask(struct device *dev,
1225 struct device_attribute *attr, char *buf)
1226{
1227 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1228 unsigned long mask;
1229 uint8_t idx;
1230
1231 spin_lock(&drvdata->spinlock);
1232 idx = drvdata->addr_idx;
1233 if (idx % 2 != 0) {
1234 spin_unlock(&drvdata->spinlock);
1235 return -EPERM;
1236 }
1237 idx = idx >> 1;
1238 if (idx >= drvdata->nr_data_cmp) {
1239 spin_unlock(&drvdata->spinlock);
1240 return -EPERM;
1241 }
1242
1243 mask = drvdata->data_mask[idx];
1244 spin_unlock(&drvdata->spinlock);
1245 return scnprintf(buf, PAGE_SIZE, "%#lx\n", mask);
1246}
1247
1248static ssize_t etm_store_data_mask(struct device *dev,
1249 struct device_attribute *attr,
1250 const char *buf, size_t size)
1251{
1252 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1253 unsigned long mask;
1254 uint8_t idx, data_idx;
1255
1256 if (sscanf(buf, "%lx", &mask) != 1)
1257 return -EINVAL;
1258
1259 spin_lock(&drvdata->spinlock);
1260 idx = drvdata->addr_idx;
1261 /* Adjust index to use the correct data comparator */
1262 data_idx = idx >> 1;
1263 /* Only idx = 0, 2, 4, 6... are valid */
1264 if (idx % 2 != 0) {
1265 spin_unlock(&drvdata->spinlock);
1266 return -EPERM;
1267 }
1268 if (data_idx >= drvdata->nr_data_cmp) {
1269 spin_unlock(&drvdata->spinlock);
1270 return -EPERM;
1271 }
1272 if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
1273 spin_unlock(&drvdata->spinlock);
1274 return -EPERM;
1275 }
1276 if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
1277 if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
1278 spin_unlock(&drvdata->spinlock);
1279 return -EPERM;
1280 }
1281 }
1282
1283 drvdata->data_mask[data_idx] = mask;
1284 spin_unlock(&drvdata->spinlock);
1285 return size;
1286}
1287static DEVICE_ATTR(data_mask, S_IRUGO | S_IWUSR, etm_show_data_mask,
1288 etm_store_data_mask);
1289
Pratik Patela9c0e062012-05-28 13:45:35 -07001290static ssize_t etm_show_cntr_idx(struct device *dev,
1291 struct device_attribute *attr, char *buf)
1292{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001293 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001294 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001295
Pratik Patel6630ebe2012-03-06 16:44:22 -08001296 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1297}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001298
Pratik Patela9c0e062012-05-28 13:45:35 -07001299static ssize_t etm_store_cntr_idx(struct device *dev,
1300 struct device_attribute *attr,
1301 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001302{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001303 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001304 unsigned long val;
1305
1306 if (sscanf(buf, "%lx", &val) != 1)
1307 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001308 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001309 return -EINVAL;
1310
Pratik Patel0a10be22012-10-23 21:12:07 -07001311 /*
1312 * Use spinlock to ensure index doesn't change while it gets
1313 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001314 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001315 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001316 drvdata->cntr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001317 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001318 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001319}
Pratik Patela9c0e062012-05-28 13:45:35 -07001320static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
1321 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001322
Pratik Patela9c0e062012-05-28 13:45:35 -07001323static ssize_t etm_show_cntr_rld_val(struct device *dev,
1324 struct device_attribute *attr, char *buf)
1325{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001326 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001327 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001328
Pratik Patel0a10be22012-10-23 21:12:07 -07001329 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001330 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001331 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001332 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1333}
1334
1335static ssize_t etm_store_cntr_rld_val(struct device *dev,
1336 struct device_attribute *attr,
1337 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001338{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001339 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001340 unsigned long val;
1341
1342 if (sscanf(buf, "%lx", &val) != 1)
1343 return -EINVAL;
1344
Pratik Patel0a10be22012-10-23 21:12:07 -07001345 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001346 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001347 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001348 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001349}
Pratik Patela9c0e062012-05-28 13:45:35 -07001350static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
1351 etm_store_cntr_rld_val);
1352
1353static ssize_t etm_show_cntr_event(struct device *dev,
1354 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001355{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001356 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001357 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001358
Pratik Patel0a10be22012-10-23 21:12:07 -07001359 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001360 val = drvdata->cntr_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001361 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001362 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1363}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001364
Pratik Patela9c0e062012-05-28 13:45:35 -07001365static ssize_t etm_store_cntr_event(struct device *dev,
1366 struct device_attribute *attr,
1367 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001368{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001369 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001370 unsigned long val;
1371
1372 if (sscanf(buf, "%lx", &val) != 1)
1373 return -EINVAL;
1374
Pratik Patel0a10be22012-10-23 21:12:07 -07001375 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001376 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001377 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001378 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001379}
Pratik Patela9c0e062012-05-28 13:45:35 -07001380static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1381 etm_store_cntr_event);
1382
1383static ssize_t etm_show_cntr_rld_event(struct device *dev,
1384 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001385{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001386 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001387 unsigned long val;
1388
Pratik Patel0a10be22012-10-23 21:12:07 -07001389 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001390 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001391 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001392 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1393}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001394
Pratik Patela9c0e062012-05-28 13:45:35 -07001395static ssize_t etm_store_cntr_rld_event(struct device *dev,
1396 struct device_attribute *attr,
1397 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001398{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001399 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001400 unsigned long val;
1401
1402 if (sscanf(buf, "%lx", &val) != 1)
1403 return -EINVAL;
1404
Pratik Patel0a10be22012-10-23 21:12:07 -07001405 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001406 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001407 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001408 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001409}
Pratik Patela9c0e062012-05-28 13:45:35 -07001410static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1411 etm_store_cntr_rld_event);
1412
1413static ssize_t etm_show_cntr_val(struct device *dev,
1414 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001415{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001416 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001417 unsigned long val;
1418
Pratik Patel0a10be22012-10-23 21:12:07 -07001419 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001420 val = drvdata->cntr_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001421 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001422 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1423}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001424
Pratik Patela9c0e062012-05-28 13:45:35 -07001425static ssize_t etm_store_cntr_val(struct device *dev,
1426 struct device_attribute *attr,
1427 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001428{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001429 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001430 unsigned long val;
1431
1432 if (sscanf(buf, "%lx", &val) != 1)
1433 return -EINVAL;
1434
Pratik Patel0a10be22012-10-23 21:12:07 -07001435 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001436 drvdata->cntr_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001437 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001438 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001439}
Pratik Patela9c0e062012-05-28 13:45:35 -07001440static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1441 etm_store_cntr_val);
1442
1443static ssize_t etm_show_seq_12_event(struct device *dev,
1444 struct device_attribute *attr, char *buf)
1445{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001446 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001447 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001448
Pratik Patela9c0e062012-05-28 13:45:35 -07001449 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1450}
1451
1452static ssize_t etm_store_seq_12_event(struct device *dev,
1453 struct device_attribute *attr,
1454 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001455{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001456 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001457 unsigned long val;
1458
Pratik Patela9c0e062012-05-28 13:45:35 -07001459 if (sscanf(buf, "%lx", &val) != 1)
1460 return -EINVAL;
1461
Pratik Patel16aefdb2012-05-30 10:41:23 -07001462 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001463 return size;
1464}
1465static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1466 etm_store_seq_12_event);
1467
1468static ssize_t etm_show_seq_21_event(struct device *dev,
1469 struct device_attribute *attr, char *buf)
1470{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001471 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001472 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001473
Pratik Patel6630ebe2012-03-06 16:44:22 -08001474 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1475}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001476
Pratik Patela9c0e062012-05-28 13:45:35 -07001477static ssize_t etm_store_seq_21_event(struct device *dev,
1478 struct device_attribute *attr,
1479 const char *buf, size_t size)
1480{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001481 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001482 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001483
Pratik Patela9c0e062012-05-28 13:45:35 -07001484 if (sscanf(buf, "%lx", &val) != 1)
1485 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001486
Pratik Patel16aefdb2012-05-30 10:41:23 -07001487 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001488 return size;
1489}
1490static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1491 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001492
Pratik Patela9c0e062012-05-28 13:45:35 -07001493static ssize_t etm_show_seq_23_event(struct device *dev,
1494 struct device_attribute *attr, 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->seq_23_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}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001501
Pratik Patela9c0e062012-05-28 13:45:35 -07001502static ssize_t etm_store_seq_23_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;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001508
Pratik Patela9c0e062012-05-28 13:45:35 -07001509 if (sscanf(buf, "%lx", &val) != 1)
1510 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001511
Pratik Patel16aefdb2012-05-30 10:41:23 -07001512 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001513 return size;
1514}
1515static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1516 etm_store_seq_23_event);
1517
1518static ssize_t etm_show_seq_31_event(struct device *dev,
1519 struct device_attribute *attr, char *buf)
1520{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001521 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001522 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001523
Pratik Patela9c0e062012-05-28 13:45:35 -07001524 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1525}
1526
1527static ssize_t etm_store_seq_31_event(struct device *dev,
1528 struct device_attribute *attr,
1529 const char *buf, size_t size)
1530{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001531 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001532 unsigned long val;
1533
1534 if (sscanf(buf, "%lx", &val) != 1)
1535 return -EINVAL;
1536
Pratik Patel16aefdb2012-05-30 10:41:23 -07001537 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001538 return size;
1539}
1540static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1541 etm_store_seq_31_event);
1542
1543static ssize_t etm_show_seq_32_event(struct device *dev,
1544 struct device_attribute *attr, char *buf)
1545{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001546 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001547 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001548
Pratik Patela9c0e062012-05-28 13:45:35 -07001549 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1550}
1551
1552static ssize_t etm_store_seq_32_event(struct device *dev,
1553 struct device_attribute *attr,
1554 const char *buf, size_t size)
1555{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001556 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001557 unsigned long val;
1558
1559 if (sscanf(buf, "%lx", &val) != 1)
1560 return -EINVAL;
1561
Pratik Patel16aefdb2012-05-30 10:41:23 -07001562 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001563 return size;
1564}
1565static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1566 etm_store_seq_32_event);
1567
1568static ssize_t etm_show_seq_13_event(struct device *dev,
1569 struct device_attribute *attr, char *buf)
1570{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001571 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001572 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001573
Pratik Patela9c0e062012-05-28 13:45:35 -07001574 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1575}
1576
1577static ssize_t etm_store_seq_13_event(struct device *dev,
1578 struct device_attribute *attr,
1579 const char *buf, size_t size)
1580{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001581 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001582 unsigned long val;
1583
1584 if (sscanf(buf, "%lx", &val) != 1)
1585 return -EINVAL;
1586
Pratik Patel16aefdb2012-05-30 10:41:23 -07001587 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001588 return size;
1589}
1590static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1591 etm_store_seq_13_event);
1592
1593static ssize_t etm_show_seq_curr_state(struct device *dev,
1594 struct device_attribute *attr, char *buf)
1595{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001596 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001597 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001598
Pratik Patela9c0e062012-05-28 13:45:35 -07001599 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1600}
1601
1602static ssize_t etm_store_seq_curr_state(struct device *dev,
1603 struct device_attribute *attr,
1604 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001605{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001606 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001607 unsigned long val;
1608
1609 if (sscanf(buf, "%lx", &val) != 1)
1610 return -EINVAL;
1611 if (val > ETM_SEQ_STATE_MAX_VAL)
1612 return -EINVAL;
1613
Pratik Patel16aefdb2012-05-30 10:41:23 -07001614 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001615 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001616}
Pratik Patela9c0e062012-05-28 13:45:35 -07001617static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1618 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001619
Pratik Patela9c0e062012-05-28 13:45:35 -07001620static ssize_t etm_show_ctxid_idx(struct device *dev,
1621 struct device_attribute *attr, char *buf)
1622{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001623 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001624 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001625
Pratik Patela9c0e062012-05-28 13:45:35 -07001626 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1627}
1628
1629static ssize_t etm_store_ctxid_idx(struct device *dev,
1630 struct device_attribute *attr,
1631 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001632{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001633 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001634 unsigned long val;
1635
1636 if (sscanf(buf, "%lx", &val) != 1)
1637 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001638 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001639 return -EINVAL;
1640
Pratik Patel0a10be22012-10-23 21:12:07 -07001641 /*
1642 * Use spinlock to ensure index doesn't change while it gets
1643 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001644 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001645 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001646 drvdata->ctxid_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001647 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001648 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001649}
Pratik Patela9c0e062012-05-28 13:45:35 -07001650static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1651 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001652
Pratik Patela9c0e062012-05-28 13:45:35 -07001653static ssize_t etm_show_ctxid_val(struct device *dev,
1654 struct device_attribute *attr, char *buf)
1655{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001656 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001657 unsigned long val;
1658
Pratik Patel0a10be22012-10-23 21:12:07 -07001659 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001660 val = drvdata->ctxid_val[drvdata->ctxid_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001661 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001662 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1663}
1664
1665static ssize_t etm_store_ctxid_val(struct device *dev,
1666 struct device_attribute *attr,
1667 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001668{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001669 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001670 unsigned long val;
1671
1672 if (sscanf(buf, "%lx", &val) != 1)
1673 return -EINVAL;
1674
Pratik Patel0a10be22012-10-23 21:12:07 -07001675 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001676 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001677 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001678 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001679}
Pratik Patela9c0e062012-05-28 13:45:35 -07001680static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1681 etm_store_ctxid_val);
1682
1683static ssize_t etm_show_ctxid_mask(struct device *dev,
1684 struct device_attribute *attr, char *buf)
1685{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001686 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001687 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001688
Pratik Patela9c0e062012-05-28 13:45:35 -07001689 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1690}
1691
1692static ssize_t etm_store_ctxid_mask(struct device *dev,
1693 struct device_attribute *attr,
1694 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001695{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001696 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001697 unsigned long val;
1698
Pratik Patela9c0e062012-05-28 13:45:35 -07001699 if (sscanf(buf, "%lx", &val) != 1)
1700 return -EINVAL;
1701
Pratik Patel16aefdb2012-05-30 10:41:23 -07001702 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001703 return size;
1704}
1705static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1706 etm_store_ctxid_mask);
1707
1708static ssize_t etm_show_sync_freq(struct device *dev,
1709 struct device_attribute *attr, char *buf)
1710{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001711 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001712 unsigned long val = drvdata->sync_freq;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001713
Pratik Patel6630ebe2012-03-06 16:44:22 -08001714 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1715}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001716
Pratik Patela9c0e062012-05-28 13:45:35 -07001717static ssize_t etm_store_sync_freq(struct device *dev,
1718 struct device_attribute *attr,
1719 const char *buf, size_t size)
1720{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001721 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001722 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001723
Pratik Patela9c0e062012-05-28 13:45:35 -07001724 if (sscanf(buf, "%lx", &val) != 1)
1725 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001726
Pratik Patel16aefdb2012-05-30 10:41:23 -07001727 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001728 return size;
1729}
1730static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1731 etm_store_sync_freq);
1732
1733static ssize_t etm_show_timestamp_event(struct device *dev,
1734 struct device_attribute *attr,
1735 char *buf)
1736{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001737 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001738 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001739
Pratik Patela9c0e062012-05-28 13:45:35 -07001740 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1741}
1742
1743static ssize_t etm_store_timestamp_event(struct device *dev,
1744 struct device_attribute *attr,
1745 const char *buf, size_t size)
1746{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001747 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001748 unsigned long val;
1749
1750 if (sscanf(buf, "%lx", &val) != 1)
1751 return -EINVAL;
1752
Pratik Patel16aefdb2012-05-30 10:41:23 -07001753 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001754 return size;
1755}
1756static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1757 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001758
Pratik Patel938e1ff2012-09-28 23:21:46 -07001759static ssize_t etm_show_pcsave(struct device *dev,
1760 struct device_attribute *attr, char *buf)
1761{
1762 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1763 unsigned long val;
1764
1765 val = drvdata->pcsave_enable;
1766 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1767}
1768
Pratik Patelb3354262012-11-30 16:15:46 -08001769static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
Pratik Patel938e1ff2012-09-28 23:21:46 -07001770{
Pratik Patel9dbfa372012-10-23 22:36:40 -07001771 int ret = 0;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001772
1773 ret = clk_prepare_enable(drvdata->clk);
1774 if (ret)
1775 return ret;
1776
Pratik Patel0a10be22012-10-23 21:12:07 -07001777 spin_lock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001778 if (val) {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001779 if (drvdata->pcsave_enable)
1780 goto out;
1781
1782 ret = smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
1783 drvdata, 1);
1784 if (ret)
1785 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001786 drvdata->pcsave_enable = true;
Pratik Patelcd2452e2012-11-15 09:57:29 -08001787 drvdata->pcsave_sticky_enable = true;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001788
1789 dev_info(drvdata->dev, "PC save enabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001790 } else {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001791 if (!drvdata->pcsave_enable)
1792 goto out;
1793
1794 ret = smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
1795 drvdata, 1);
1796 if (ret)
1797 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001798 drvdata->pcsave_enable = false;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001799
1800 dev_info(drvdata->dev, "PC save disabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001801 }
Pratik Patel9dbfa372012-10-23 22:36:40 -07001802out:
Pratik Patel0a10be22012-10-23 21:12:07 -07001803 spin_unlock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001804
1805 clk_disable_unprepare(drvdata->clk);
Pratik Patel9dbfa372012-10-23 22:36:40 -07001806 return ret;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001807}
1808
1809static ssize_t etm_store_pcsave(struct device *dev,
1810 struct device_attribute *attr,
1811 const char *buf, size_t size)
1812{
1813 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1814 unsigned long val;
1815 int ret;
1816
1817 if (sscanf(buf, "%lx", &val) != 1)
1818 return -EINVAL;
1819
1820 ret = __etm_store_pcsave(drvdata, val);
1821 if (ret)
1822 return ret;
1823
1824 return size;
1825}
1826static DEVICE_ATTR(pcsave, S_IRUGO | S_IWUSR, etm_show_pcsave,
1827 etm_store_pcsave);
1828
Pratik Patel6630ebe2012-03-06 16:44:22 -08001829static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001830 &dev_attr_nr_addr_cmp.attr,
1831 &dev_attr_nr_cntr.attr,
1832 &dev_attr_nr_ctxid_cmp.attr,
1833 &dev_attr_reset.attr,
1834 &dev_attr_mode.attr,
1835 &dev_attr_trigger_event.attr,
1836 &dev_attr_enable_event.attr,
1837 &dev_attr_fifofull_level.attr,
1838 &dev_attr_addr_idx.attr,
1839 &dev_attr_addr_single.attr,
1840 &dev_attr_addr_range.attr,
1841 &dev_attr_addr_start.attr,
1842 &dev_attr_addr_stop.attr,
1843 &dev_attr_addr_acctype.attr,
Pushkar Joshi85688c62012-12-06 10:52:02 -08001844 &dev_attr_data_val.attr,
1845 &dev_attr_data_mask.attr,
Pratik Patela9c0e062012-05-28 13:45:35 -07001846 &dev_attr_cntr_idx.attr,
1847 &dev_attr_cntr_rld_val.attr,
1848 &dev_attr_cntr_event.attr,
1849 &dev_attr_cntr_rld_event.attr,
1850 &dev_attr_cntr_val.attr,
1851 &dev_attr_seq_12_event.attr,
1852 &dev_attr_seq_21_event.attr,
1853 &dev_attr_seq_23_event.attr,
1854 &dev_attr_seq_31_event.attr,
1855 &dev_attr_seq_32_event.attr,
1856 &dev_attr_seq_13_event.attr,
1857 &dev_attr_seq_curr_state.attr,
1858 &dev_attr_ctxid_idx.attr,
1859 &dev_attr_ctxid_val.attr,
1860 &dev_attr_ctxid_mask.attr,
1861 &dev_attr_sync_freq.attr,
1862 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001863 NULL,
1864};
1865
1866static struct attribute_group etm_attr_grp = {
1867 .attrs = etm_attrs,
1868};
1869
Pratik Patel3b0ca882012-06-01 16:54:14 -07001870static const struct attribute_group *etm_attr_grps[] = {
1871 &etm_attr_grp,
1872 NULL,
1873};
1874
Pratik Patel97a08f32012-10-22 11:47:41 -07001875static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
1876 void *hcpu)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001877{
Pratik Patel97a08f32012-10-22 11:47:41 -07001878 unsigned int cpu = (unsigned long)hcpu;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001879
Pratik Patelb3354262012-11-30 16:15:46 -08001880 if (!etmdrvdata[cpu])
1881 goto out;
1882
Pratik Patel97a08f32012-10-22 11:47:41 -07001883 switch (action & (~CPU_TASKS_FROZEN)) {
1884 case CPU_STARTING:
Pratik Patelb3354262012-11-30 16:15:46 -08001885 spin_lock(&etmdrvdata[cpu]->spinlock);
1886 if (!etmdrvdata[cpu]->os_unlock) {
Pratik Patel97a08f32012-10-22 11:47:41 -07001887 etm_os_unlock(etmdrvdata[cpu]);
1888 etmdrvdata[cpu]->os_unlock = true;
Pratik Patel97a08f32012-10-22 11:47:41 -07001889 }
1890
Pratik Pateldbb352b2013-01-22 18:23:57 -08001891 if (etmdrvdata[cpu]->enable && etmdrvdata[cpu]->round_robin)
Pratik Patel97a08f32012-10-22 11:47:41 -07001892 __etm_enable(etmdrvdata[cpu]);
Pratik Patelb3354262012-11-30 16:15:46 -08001893 spin_unlock(&etmdrvdata[cpu]->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -07001894 break;
1895
Pratik Patelcd2452e2012-11-15 09:57:29 -08001896 case CPU_ONLINE:
Pratik Patelb7fd0602012-11-28 15:29:02 -08001897 if (etmdrvdata[cpu]->boot_enable &&
1898 !etmdrvdata[cpu]->sticky_enable)
1899 coresight_enable(etmdrvdata[cpu]->csdev);
1900
Pratik Patelb3354262012-11-30 16:15:46 -08001901 if (etmdrvdata[cpu]->pcsave_boot_enable &&
1902 !etmdrvdata[cpu]->pcsave_sticky_enable)
1903 __etm_store_pcsave(etmdrvdata[cpu], 1);
Pratik Patelcd2452e2012-11-15 09:57:29 -08001904 break;
1905
Pratik Patel97a08f32012-10-22 11:47:41 -07001906 case CPU_DYING:
Pratik Patelb3354262012-11-30 16:15:46 -08001907 spin_lock(&etmdrvdata[cpu]->spinlock);
Pratik Pateldbb352b2013-01-22 18:23:57 -08001908 if (etmdrvdata[cpu]->enable && etmdrvdata[cpu]->round_robin)
Pratik Patel97a08f32012-10-22 11:47:41 -07001909 __etm_disable(etmdrvdata[cpu]);
Pratik Patelb3354262012-11-30 16:15:46 -08001910 spin_unlock(&etmdrvdata[cpu]->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -07001911 break;
1912 }
Pratik Patelb3354262012-11-30 16:15:46 -08001913out:
Pratik Patel97a08f32012-10-22 11:47:41 -07001914 return NOTIFY_OK;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001915}
1916
Pratik Patel97a08f32012-10-22 11:47:41 -07001917static struct notifier_block etm_cpu_notifier = {
1918 .notifier_call = etm_cpu_callback,
1919};
1920
Stephen Boyda9510502012-04-24 16:23:34 -07001921static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001922{
Pratik Patel61de7302012-03-07 12:06:10 -08001923 switch (arch) {
1924 case PFT_ARCH_V1_1:
1925 break;
Pushkar Joshi85688c62012-12-06 10:52:02 -08001926 case ETM_ARCH_V3_5:
1927 break;
Pratik Patel61de7302012-03-07 12:06:10 -08001928 default:
1929 return false;
1930 }
1931 return true;
1932}
1933
Pratik Patele6e41da2012-09-12 12:50:29 -07001934static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001935{
Pratik Patel61de7302012-03-07 12:06:10 -08001936 uint32_t etmidr;
1937 uint32_t etmccr;
Pushkar Joshi85688c62012-12-06 10:52:02 -08001938 uint32_t etmcr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001939 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001940
Pratik Patel3b0ca882012-06-01 16:54:14 -07001941 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001942 /*
1943 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
1944 * memory mapped interface and so use it first to enable power/clock
1945 * to allow subsequent cp14 accesses.
1946 */
Pratik Patelef6da292012-09-17 17:37:19 -07001947 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -07001948 /*
1949 * Clear power down bit since when this bit is set writes to
1950 * certain registers might be ignored.
1951 */
1952 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -08001953 etm_clr_pwrup(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001954 /* Set prog bit. It will be set from reset but this is included to
1955 * ensure it is set
1956 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001957 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001958
1959 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001960 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001961 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001962
Pratik Patel3b0ca882012-06-01 16:54:14 -07001963 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001964 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1965 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1966 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1967 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1968 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pushkar Joshi85688c62012-12-06 10:52:02 -08001969 drvdata->nr_data_cmp = BMVAL(etmccr, 4, 7);
1970
1971 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
1972 etmcr = etm_readl(drvdata, ETMCR);
1973 etmcr |= (BIT(2) | BIT(3));
1974 etm_writel(drvdata, etmcr, ETMCR);
1975 etmcr = etm_readl(drvdata, ETMCR);
1976 if (BVAL(etmcr, 2) || BVAL(etmcr, 3))
1977 drvdata->data_trace_support = true;
1978 else
1979 drvdata->data_trace_support = false;
1980 } else
1981 drvdata->data_trace_support = false;
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001982
Pratik Pateld1d65c92012-09-25 23:37:43 -07001983 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001984 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001985}
1986
Pratik Patelc14b4df2012-09-05 18:07:59 -07001987static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1988{
Pratik Patel97a08f32012-10-22 11:47:41 -07001989 drvdata->arch = etmdrvdata[0]->arch;
1990 drvdata->nr_addr_cmp = etmdrvdata[0]->nr_addr_cmp;
1991 drvdata->nr_cntr = etmdrvdata[0]->nr_cntr;
1992 drvdata->nr_ext_inp = etmdrvdata[0]->nr_ext_inp;
1993 drvdata->nr_ext_out = etmdrvdata[0]->nr_ext_out;
1994 drvdata->nr_ctxid_cmp = etmdrvdata[0]->nr_ctxid_cmp;
Pushkar Joshi85688c62012-12-06 10:52:02 -08001995 drvdata->nr_data_cmp = etmdrvdata[0]->nr_data_cmp;
1996 drvdata->data_trace_support = etmdrvdata[0]->data_trace_support;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001997}
1998
Pratik Patel3b0ca882012-06-01 16:54:14 -07001999static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07002000{
2001 int i;
2002
2003 drvdata->trigger_event = 0x406F;
2004 drvdata->enable_event = 0x6F;
2005 drvdata->enable_ctrl1 = 0x1;
2006 drvdata->fifofull_level = 0x28;
2007 if (drvdata->nr_addr_cmp >= 2) {
2008 drvdata->addr_val[0] = (uint32_t) _stext;
2009 drvdata->addr_val[1] = (uint32_t) _etext;
2010 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
2011 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
Pushkar Joshi85688c62012-12-06 10:52:02 -08002012 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
2013 drvdata->addr_acctype[0] = 0x19;
2014 drvdata->addr_acctype[1] = 0x19;
2015 }
Pratik Patel16aefdb2012-05-30 10:41:23 -07002016 }
2017 for (i = 0; i < drvdata->nr_cntr; i++) {
2018 drvdata->cntr_event[i] = 0x406F;
2019 drvdata->cntr_rld_event[i] = 0x406F;
2020 }
2021 drvdata->seq_12_event = 0x406F;
2022 drvdata->seq_21_event = 0x406F;
2023 drvdata->seq_23_event = 0x406F;
2024 drvdata->seq_31_event = 0x406F;
2025 drvdata->seq_32_event = 0x406F;
2026 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07002027 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
2028 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
2029 drvdata->sync_freq = 0x100;
2030 else
2031 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07002032 drvdata->timestamp_event = 0x406F;
2033
2034 /* Overrides for Krait pass1 */
2035 if (cpu_is_krait_v1()) {
2036 /* Krait pass1 doesn't support include filtering and non-cycle
2037 * accurate tracing
2038 */
2039 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
2040 drvdata->ctrl = 0x1000;
2041 drvdata->enable_ctrl1 = 0x1000000;
2042 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
2043 drvdata->addr_val[i] = 0x0;
2044 drvdata->addr_acctype[i] = 0x0;
2045 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
2046 }
2047 }
Pushkar Joshi85688c62012-12-06 10:52:02 -08002048
2049 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
2050 drvdata->ctrl |= BIT(11);
2051 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
2052 drvdata->enable_ctrl2 = 0x0;
2053 if (drvdata->data_trace_support == true) {
2054 drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
2055 ETM_MODE_DATA_TRACE_ADDR);
2056 drvdata->ctrl |= BIT(2) | BIT(3);
2057 drvdata->viewdata_ctrl1 = 0x0;
2058 drvdata->viewdata_ctrl3 = 0x10000;
2059 drvdata->viewdata_event = 0x6F;
2060 }
2061 for (i = 0; i < drvdata->nr_data_cmp; i++) {
2062 drvdata->data_val[i] = 0;
2063 drvdata->data_mask[i] = ~(0);
2064 }
Pratik Patel16aefdb2012-05-30 10:41:23 -07002065}
2066
Pratik Patel492b3012012-03-06 14:22:30 -08002067static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07002068{
Pratik Patele5771792011-09-17 18:33:54 -07002069 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07002070 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07002071 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002072 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07002073 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07002074 uint32_t reg_size;
2075 static int count;
2076 void *baddr;
2077 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002078 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07002079
Pratik Patel5f6d1af2012-06-13 15:48:13 -07002080 if (pdev->dev.of_node) {
2081 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
2082 if (IS_ERR(pdata))
2083 return PTR_ERR(pdata);
2084 pdev->dev.platform_data = pdata;
2085 }
2086
Pratik Patel4a1b2522012-06-17 15:31:15 -07002087 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
2088 if (!drvdata)
2089 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07002090 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002091 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07002092
Aparna Dasc9907512013-03-08 10:20:52 -08002093 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "etm-base");
Pratik Patel4a1b2522012-06-17 15:31:15 -07002094 if (!res)
2095 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07002096 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07002097
Pratik Patel4a1b2522012-06-17 15:31:15 -07002098 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
2099 if (!drvdata->base)
2100 return -ENOMEM;
2101
Pratik Patel0a10be22012-10-23 21:12:07 -07002102 spin_lock_init(&drvdata->spinlock);
Pratik Patel3b0ca882012-06-01 16:54:14 -07002103 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07002104
Pratik Patel4a1b2522012-06-17 15:31:15 -07002105 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07002106 if (IS_ERR(drvdata->clk)) {
2107 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07002108 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07002109 }
Pratik Patel2c09b762012-07-21 15:54:54 -07002110
Pratik Patel6fb38342012-06-03 14:51:38 -07002111 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07002112 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07002113 goto err0;
2114
Pratik Patel16aefdb2012-05-30 10:41:23 -07002115 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07002116 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07002117 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07002118
Pratik Patel97a08f32012-10-22 11:47:41 -07002119 drvdata->cpu = count++;
2120
2121 get_online_cpus();
2122 etmdrvdata[drvdata->cpu] = drvdata;
2123
Pushkar Joshicba120a2013-03-05 18:37:39 -08002124 if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, drvdata, 1))
Pratik Patel97a08f32012-10-22 11:47:41 -07002125 drvdata->os_unlock = true;
2126 /*
2127 * Use CPU0 to populate read-only configuration data for ETM0. For
2128 * other ETMs copy it over from ETM0.
Pratik Patelc14b4df2012-09-05 18:07:59 -07002129 */
2130 if (drvdata->cpu == 0) {
Pratik Patel97a08f32012-10-22 11:47:41 -07002131 register_hotcpu_notifier(&etm_cpu_notifier);
2132 if (smp_call_function_single(drvdata->cpu, etm_init_arch_data,
2133 drvdata, 1))
2134 dev_err(dev, "ETM arch init failed\n");
Pratik Patelc14b4df2012-09-05 18:07:59 -07002135 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07002136 etm_copy_arch_data(drvdata);
2137 }
Pratik Patel97a08f32012-10-22 11:47:41 -07002138
2139 put_online_cpus();
2140
Pratik Pateldc3a0a42012-09-11 17:48:23 -07002141 if (etm_arch_supported(drvdata->arch) == false) {
2142 ret = -EINVAL;
2143 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07002144 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07002145 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07002146
Pratik Patel16aefdb2012-05-30 10:41:23 -07002147 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07002148
Pratik Pateldbb352b2013-01-22 18:23:57 -08002149 if (pdev->dev.of_node)
2150 drvdata->round_robin = of_property_read_bool(pdev->dev.of_node,
2151 "qcom,round-robin");
2152
Pratik Patel26477792012-09-07 01:35:36 -07002153 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
2154 if (baddr) {
2155 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
2156 dump.id = MSM_ETM0_REG + drvdata->cpu;
2157 dump.start_addr = virt_to_phys(baddr);
2158 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
2159 ret = msm_dump_table_register(&dump);
2160 if (ret) {
2161 devm_kfree(dev, baddr);
Pratik Patel97a08f32012-10-22 11:47:41 -07002162 dev_err(dev, "ETM REG dump setup failed/unsupported\n");
Pratik Patel26477792012-09-07 01:35:36 -07002163 }
2164 } else {
2165 dev_err(dev, "ETM REG dump space allocation failed\n");
2166 }
2167
Pratik Patel4a1b2522012-06-17 15:31:15 -07002168 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07002169 if (!desc) {
2170 ret = -ENOMEM;
Pratik Patel97a08f32012-10-22 11:47:41 -07002171 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002172 }
2173 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
2174 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
2175 desc->ops = &etm_cs_ops;
2176 desc->pdata = pdev->dev.platform_data;
2177 desc->dev = &pdev->dev;
2178 desc->groups = etm_attr_grps;
2179 desc->owner = THIS_MODULE;
2180 drvdata->csdev = coresight_register(desc);
2181 if (IS_ERR(drvdata->csdev)) {
2182 ret = PTR_ERR(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07002183 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002184 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07002185
Pratik Patel938e1ff2012-09-28 23:21:46 -07002186 if (pdev->dev.of_node)
2187 drvdata->pcsave_impl = of_property_read_bool(pdev->dev.of_node,
2188 "qcom,pc-save");
2189 if (drvdata->pcsave_impl) {
2190 ret = device_create_file(&drvdata->csdev->dev,
2191 &dev_attr_pcsave);
2192 if (ret)
2193 dev_err(dev, "ETM pcsave dev node creation failed\n");
2194 }
2195
Pratik Patel4a1b2522012-06-17 15:31:15 -07002196 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07002197
Pratik Patelb7fd0602012-11-28 15:29:02 -08002198 if (boot_enable) {
Pratik Patel3b0ca882012-06-01 16:54:14 -07002199 coresight_enable(drvdata->csdev);
Pratik Patelb7fd0602012-11-28 15:29:02 -08002200 drvdata->boot_enable = true;
2201 }
Pratik Patel7831c082011-06-08 21:44:37 -07002202
Pratik Patelcd2452e2012-11-15 09:57:29 -08002203 if (drvdata->pcsave_impl && boot_pcsave_enable) {
2204 __etm_store_pcsave(drvdata, 1);
2205 drvdata->pcsave_boot_enable = true;
2206 }
Pratik Patel938e1ff2012-09-28 23:21:46 -07002207
Pratik Patel7831c082011-06-08 21:44:37 -07002208 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -07002209err2:
2210 if (drvdata->cpu == 0)
2211 unregister_hotcpu_notifier(&etm_cpu_notifier);
2212 wake_lock_destroy(&drvdata->wake_lock);
2213 return ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07002214err1:
Pratik Patel97a08f32012-10-22 11:47:41 -07002215 if (drvdata->cpu == 0)
2216 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07002217 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07002218err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07002219 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07002220 return ret;
2221}
2222
Pratik Patelf6fe9182012-03-20 14:04:18 -07002223static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07002224{
Pratik Patel3b0ca882012-06-01 16:54:14 -07002225 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
2226
Pratik Patel938e1ff2012-09-28 23:21:46 -07002227 device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
Pratik Patel3b0ca882012-06-01 16:54:14 -07002228 coresight_unregister(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07002229 if (drvdata->cpu == 0)
2230 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07002231 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07002232 return 0;
2233}
2234
Pratik Patel9eae4822012-05-14 17:34:53 -07002235static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07002236 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07002237 {}
2238};
2239
Pratik Patel492b3012012-03-06 14:22:30 -08002240static struct platform_driver etm_driver = {
2241 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07002242 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07002243 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07002244 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07002245 .owner = THIS_MODULE,
2246 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07002247 },
2248};
2249
Pratik Patel492b3012012-03-06 14:22:30 -08002250int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07002251{
Pratik Patel492b3012012-03-06 14:22:30 -08002252 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07002253}
Pratik Patelf6fe9182012-03-20 14:04:18 -07002254module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07002255
Pratik Patelf6fe9182012-03-20 14:04:18 -07002256void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07002257{
Pratik Patel492b3012012-03-06 14:22:30 -08002258 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07002259}
Pratik Patelf6fe9182012-03-20 14:04:18 -07002260module_exit(etm_exit);
2261
2262MODULE_LICENSE("GPL v2");
2263MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");