blob: 16ed8589b71d4eab09b56000a94df666aee9bf1c [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 Patel3b0ca882012-06-01 16:54:14 -0700176enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800177 ETM_ADDR_TYPE_NONE,
178 ETM_ADDR_TYPE_SINGLE,
179 ETM_ADDR_TYPE_RANGE,
180 ETM_ADDR_TYPE_START,
181 ETM_ADDR_TYPE_STOP,
182};
183
Pratik Patel29cba152012-01-03 11:40:26 -0800184#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700185static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800186#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700187static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800188#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700189module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700190 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700191);
192
Pratik Patel938e1ff2012-09-28 23:21:46 -0700193#ifdef CONFIG_MSM_QDSS_ETM_PCSAVE_DEFAULT_ENABLE
194static int boot_pcsave_enable = 1;
195#else
196static int boot_pcsave_enable;
197#endif
198module_param_named(
199 boot_pcsave_enable, boot_pcsave_enable, int, S_IRUGO
200);
201
Pratik Patel16aefdb2012-05-30 10:41:23 -0700202struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700203 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700204 struct device *dev;
205 struct coresight_device *csdev;
206 struct clk *clk;
Pratik Patel0a10be22012-10-23 21:12:07 -0700207 spinlock_t spinlock;
Pratik Patel7831c082011-06-08 21:44:37 -0700208 struct wake_lock wake_lock;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700209 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800210 uint8_t arch;
Pratik Patelf3238df2012-10-19 16:19:12 -0700211 bool enable;
Pratik Patel97a08f32012-10-22 11:47:41 -0700212 bool os_unlock;
Pratik Patel61de7302012-03-07 12:06:10 -0800213 uint8_t nr_addr_cmp;
214 uint8_t nr_cntr;
215 uint8_t nr_ext_inp;
216 uint8_t nr_ext_out;
217 uint8_t nr_ctxid_cmp;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800218 uint8_t nr_data_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800219 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800220 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800221 uint32_t ctrl;
222 uint32_t trigger_event;
223 uint32_t startstop_ctrl;
224 uint32_t enable_event;
225 uint32_t enable_ctrl1;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800226 uint32_t enable_ctrl2;
Pratik Patel61de7302012-03-07 12:06:10 -0800227 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800228 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800229 uint32_t addr_val[ETM_MAX_ADDR_CMP];
230 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800231 uint32_t addr_type[ETM_MAX_ADDR_CMP];
Pushkar Joshi85688c62012-12-06 10:52:02 -0800232 bool data_trace_support;
233 uint32_t data_val[ETM_MAX_ADDR_CMP];
234 uint32_t data_mask[ETM_MAX_ADDR_CMP];
235 uint32_t viewdata_event;
236 uint32_t viewdata_ctrl1;
237 uint32_t viewdata_ctrl3;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800238 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800239 uint32_t cntr_rld_val[ETM_MAX_CNTR];
240 uint32_t cntr_event[ETM_MAX_CNTR];
241 uint32_t cntr_rld_event[ETM_MAX_CNTR];
242 uint32_t cntr_val[ETM_MAX_CNTR];
243 uint32_t seq_12_event;
244 uint32_t seq_21_event;
245 uint32_t seq_23_event;
246 uint32_t seq_31_event;
247 uint32_t seq_32_event;
248 uint32_t seq_13_event;
249 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800250 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800251 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
252 uint32_t ctxid_mask;
253 uint32_t sync_freq;
254 uint32_t timestamp_event;
Pratik Patel938e1ff2012-09-28 23:21:46 -0700255 bool pcsave_impl;
256 bool pcsave_enable;
Pratik Patelcd2452e2012-11-15 09:57:29 -0800257 bool pcsave_sticky_enable;
258 bool pcsave_boot_enable;
Pratik Patel7831c082011-06-08 21:44:37 -0700259};
260
Pratik Patel97a08f32012-10-22 11:47:41 -0700261static struct etm_drvdata *etmdrvdata[NR_CPUS];
262
263/*
264 * Memory mapped writes to clear os lock are not supported on Krait v1, v2
265 * and OS lock must be unlocked before any memory mapped access, otherwise
266 * memory mapped reads/writes will be invalid.
267 */
268static void etm_os_unlock(void *info)
269{
Pushkar Joshi85688c62012-12-06 10:52:02 -0800270 if (cpu_is_krait()) {
271 etm_writel_cp14(0x0, ETMOSLAR);
272 isb();
273 }
Pratik Patel97a08f32012-10-22 11:47:41 -0700274}
Pratik Patelc14b4df2012-09-05 18:07:59 -0700275
Pratik Pateld1d65c92012-09-25 23:37:43 -0700276/*
277 * ETM clock is derived from the processor clock and gets enabled on a
278 * logical OR of below items on Krait (v2 onwards):
Pratik Patel17f3b822011-11-21 12:41:47 -0800279 * 1.CPMR[ETMCLKEN] is 1
280 * 2.ETMCR[PD] is 0
281 * 3.ETMPDCR[PU] is 1
282 * 4.Reset is asserted (core or debug)
283 * 5.APB memory mapped requests (eg. EDAP access)
284 *
285 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
286 * enables
287 *
Pratik Pateld1d65c92012-09-25 23:37:43 -0700288 * We rely on 5. to be able to access ETMCR/ETMPDCR and then use 2./3. above
289 * for ETM clock vote in the driver and the save-restore code uses 1. above
Pratik Patel17f3b822011-11-21 12:41:47 -0800290 * for its vote
291 */
Pratik Pateld1d65c92012-09-25 23:37:43 -0700292static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
293{
294 uint32_t etmcr;
295
296 /* ensure pending cp14 accesses complete before setting pwrdwn */
297 mb();
298 isb();
299 etmcr = etm_readl(drvdata, ETMCR);
300 etmcr |= BIT(0);
301 etm_writel(drvdata, etmcr, ETMCR);
302}
303
304static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
305{
306 uint32_t etmcr;
307
308 etmcr = etm_readl(drvdata, ETMCR);
309 etmcr &= ~BIT(0);
310 etm_writel(drvdata, etmcr, ETMCR);
311 /* ensure pwrup completes before subsequent cp14 accesses */
312 mb();
313 isb();
314}
315
Pratik Patelef6da292012-09-17 17:37:19 -0700316static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700317{
Pratik Patelef6da292012-09-17 17:37:19 -0700318 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700319
Pratik Patele6e41da2012-09-12 12:50:29 -0700320 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700321 etmpdcr |= BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700322 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
323 /* ensure pwrup completes before subsequent cp14 accesses */
324 mb();
325 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700326}
327
Pratik Patelef6da292012-09-17 17:37:19 -0700328static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700329{
Pratik Patelef6da292012-09-17 17:37:19 -0700330 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700331
Pratik Patele6e41da2012-09-12 12:50:29 -0700332 /* ensure pending cp14 accesses complete before clearing pwrup */
333 mb();
334 isb();
335 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700336 etmpdcr &= ~BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700337 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700338}
339
Pratik Patel3b0ca882012-06-01 16:54:14 -0700340static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700341{
342 uint32_t etmcr;
343 int count;
344
Pratik Patel3b0ca882012-06-01 16:54:14 -0700345 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700346 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700347 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700348 /* recommended by spec for cp14 accesses to ensure etmcr write is
349 * complete before polling etmsr
350 */
351 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700352 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700353 && count > 0; count--)
354 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800355 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700356 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700357}
358
Pratik Patel3b0ca882012-06-01 16:54:14 -0700359static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700360{
361 uint32_t etmcr;
362 int count;
363
Pratik Patel3b0ca882012-06-01 16:54:14 -0700364 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700365 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700366 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700367 /* recommended by spec for cp14 accesses to ensure etmcr write is
368 * complete before polling etmsr
369 */
370 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700371 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700372 && count > 0; count--)
373 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800374 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700375 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700376}
377
Pratik Patel938e1ff2012-09-28 23:21:46 -0700378static void etm_enable_pcsave(void *info)
379{
380 struct etm_drvdata *drvdata = info;
381
382 ETM_UNLOCK(drvdata);
383
Pratik Patel938e1ff2012-09-28 23:21:46 -0700384 /*
385 * ETMPDCR is only accessible via memory mapped interface and so use
386 * it first to enable power/clock to allow subsequent cp14 accesses.
387 */
388 etm_set_pwrup(drvdata);
389 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800390 etm_clr_pwrup(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700391
392 ETM_LOCK(drvdata);
393}
394
395static void etm_disable_pcsave(void *info)
396{
397 struct etm_drvdata *drvdata = info;
398
399 ETM_UNLOCK(drvdata);
400
Pratik Patelf95c5402012-11-05 18:21:08 -0800401 if (!drvdata->enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700402 etm_set_pwrdwn(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700403
404 ETM_LOCK(drvdata);
405}
406
Pushkar Joshi85688c62012-12-06 10:52:02 -0800407static bool etm_version_gte(uint8_t arch, uint8_t base_arch)
408{
409 if (arch >= base_arch && ((arch & PFT_ARCH_MAJOR) != PFT_ARCH_MAJOR))
410 return true;
411 else
412 return false;
413}
414
Pratik Patel66e1a412012-09-06 11:07:06 -0700415static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700416{
Pratik Patel17f3b822011-11-21 12:41:47 -0800417 int i;
Pratik Pateld1d65c92012-09-25 23:37:43 -0700418 uint32_t etmcr;
Pratik Patel66e1a412012-09-06 11:07:06 -0700419 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700420
Pratik Patel3b0ca882012-06-01 16:54:14 -0700421 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700422 /*
423 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
424 * memory mapped interface and so use it first to enable power/clock
425 * to allow subsequent cp14 accesses.
426 */
Pratik Patelef6da292012-09-17 17:37:19 -0700427 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -0700428 /*
429 * Clear power down bit since when this bit is set writes to
Pratik Patelf3238df2012-10-19 16:19:12 -0700430 * certain registers might be ignored. This is also a pre-requisite
431 * for trace enable.
Pratik Pateld1d65c92012-09-25 23:37:43 -0700432 */
433 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800434 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700435 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700436
Pratik Pateld1d65c92012-09-25 23:37:43 -0700437 etmcr = etm_readl(drvdata, ETMCR);
438 etmcr &= (BIT(10) | BIT(0));
439 etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700440 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
441 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
Pushkar Joshi85688c62012-12-06 10:52:02 -0800442 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
443 etm_writel(drvdata, drvdata->enable_ctrl2, ETMTECR2);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700444 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
445 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
446 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pushkar Joshi85688c62012-12-06 10:52:02 -0800447 if (drvdata->data_trace_support == true) {
448 etm_writel(drvdata, drvdata->viewdata_event, ETMVDEVR);
449 etm_writel(drvdata, drvdata->viewdata_ctrl1, ETMVDCR1);
450 etm_writel(drvdata, drvdata->viewdata_ctrl3, ETMVDCR3);
451 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700452 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700453 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
454 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700455 }
Pushkar Joshi85688c62012-12-06 10:52:02 -0800456 for (i = 0; i < drvdata->nr_data_cmp; i++) {
457 etm_writel(drvdata, drvdata->data_val[i], ETMDCVRn(i));
458 etm_writel(drvdata, drvdata->data_mask[i], ETMDCMRn(i));
459 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700460 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700461 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
462 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
463 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700464 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700465 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800466 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700467 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
468 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
469 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
470 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
471 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
472 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
473 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700474 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700475 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700476 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700477 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
478 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
479 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
480 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
481 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
482 etm_writel(drvdata, 0x00000000, ETMAUXCR);
483 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
484 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800485
Pratik Patel3b0ca882012-06-01 16:54:14 -0700486 etm_clr_prog(drvdata);
487 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700488
489 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700490}
491
Pratik Patel3b0ca882012-06-01 16:54:14 -0700492static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700493{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700494 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
495 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800496
Pratik Patel16aefdb2012-05-30 10:41:23 -0700497 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700498
Pratik Patel16aefdb2012-05-30 10:41:23 -0700499 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700500 if (ret)
501 goto err_clk;
502
Pratik Patel0a10be22012-10-23 21:12:07 -0700503 spin_lock(&drvdata->spinlock);
504
Pratik Patelf3238df2012-10-19 16:19:12 -0700505 /*
506 * Executing __etm_enable on the cpu whose ETM is being enabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700507 * ensures that register writes occur when cpu is powered.
508 */
Pratik Patel97a08f32012-10-22 11:47:41 -0700509 ret = smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
510 if (ret)
511 goto err;
Pratik Patelf3238df2012-10-19 16:19:12 -0700512 drvdata->enable = true;
Pratik Patel0a10be22012-10-23 21:12:07 -0700513
514 spin_unlock(&drvdata->spinlock);
Pratik Patel7831c082011-06-08 21:44:37 -0700515
Pratik Patel16aefdb2012-05-30 10:41:23 -0700516 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700517
Pratik Patel16aefdb2012-05-30 10:41:23 -0700518 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700519 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -0700520err:
521 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700522 clk_disable_unprepare(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700523err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700524 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800525 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700526}
527
Pratik Patel66e1a412012-09-06 11:07:06 -0700528static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700529{
Pratik Patel66e1a412012-09-06 11:07:06 -0700530 struct etm_drvdata *drvdata = info;
531
Pratik Patel3b0ca882012-06-01 16:54:14 -0700532 ETM_UNLOCK(drvdata);
533 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700534
Pratik Patel17f3b822011-11-21 12:41:47 -0800535 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700536 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700537
Pratik Patelf95c5402012-11-05 18:21:08 -0800538 if (!drvdata->pcsave_enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700539 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700540 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700541
542 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700543}
544
Pratik Patel3b0ca882012-06-01 16:54:14 -0700545static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700546{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700547 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800548
Pratik Patel16aefdb2012-05-30 10:41:23 -0700549 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700550
Pratik Patelb3354262012-11-30 16:15:46 -0800551 /*
552 * Taking hotplug lock here protects from clocks getting disabled
553 * with tracing being left on (crash scenario) if user disable occurs
554 * after cpu online mask indicates the cpu is offline but before the
555 * DYING hotplug callback is serviced by the ETM driver.
556 */
Pratik Patel97a08f32012-10-22 11:47:41 -0700557 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -0700558 spin_lock(&drvdata->spinlock);
559
Pratik Patelf3238df2012-10-19 16:19:12 -0700560 /*
561 * Executing __etm_disable on the cpu whose ETM is being disabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700562 * ensures that register writes occur when cpu is powered.
563 */
564 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patelf3238df2012-10-19 16:19:12 -0700565 drvdata->enable = false;
Pratik Patel0a10be22012-10-23 21:12:07 -0700566
567 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700568 put_online_cpus();
Pratik Patel7831c082011-06-08 21:44:37 -0700569
Pratik Patel16aefdb2012-05-30 10:41:23 -0700570 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700571
Pratik Patel16aefdb2012-05-30 10:41:23 -0700572 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700573
Pratik Patel16aefdb2012-05-30 10:41:23 -0700574 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700575}
576
Pratik Patel3b0ca882012-06-01 16:54:14 -0700577static const struct coresight_ops_source etm_source_ops = {
578 .enable = etm_enable,
579 .disable = etm_disable,
580};
Pratik Patel17f3b822011-11-21 12:41:47 -0800581
Pratik Patel3b0ca882012-06-01 16:54:14 -0700582static const struct coresight_ops etm_cs_ops = {
583 .source_ops = &etm_source_ops,
584};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800585
Pratik Patela9c0e062012-05-28 13:45:35 -0700586static ssize_t etm_show_nr_addr_cmp(struct device *dev,
587 struct device_attribute *attr, char *buf)
588{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700589 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700590 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700591
Pratik Patela9c0e062012-05-28 13:45:35 -0700592 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
593}
594static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
595
596static ssize_t etm_show_nr_cntr(struct device *dev,
597 struct device_attribute *attr, char *buf)
598{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700599 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700600 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700601
Pratik Patela9c0e062012-05-28 13:45:35 -0700602 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
603}
604static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
605
606static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
607 struct device_attribute *attr, char *buf)
608{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700609 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700610 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700611
Pratik Patela9c0e062012-05-28 13:45:35 -0700612 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
613}
614static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
615
616static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
617 char *buf)
618{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700619 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700620 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700621
Pratik Patela9c0e062012-05-28 13:45:35 -0700622 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
623}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800624
Pratik Pateld30deda2012-02-01 14:40:55 -0800625/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700626static ssize_t etm_store_reset(struct device *dev,
627 struct device_attribute *attr, const char *buf,
628 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800629{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700630 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800631 int i;
632 unsigned long val;
633
634 if (sscanf(buf, "%lx", &val) != 1)
635 return -EINVAL;
636
Pratik Patel0a10be22012-10-23 21:12:07 -0700637 spin_lock(&drvdata->spinlock);
Pratik Pateld30deda2012-02-01 14:40:55 -0800638 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700639 drvdata->mode = ETM_MODE_EXCLUDE;
640 drvdata->ctrl = 0x0;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800641 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
642 drvdata->ctrl |= BIT(11);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800643 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700644 drvdata->mode |= ETM_MODE_CYCACC;
645 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800646 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700647 drvdata->trigger_event = 0x406F;
648 drvdata->startstop_ctrl = 0x0;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800649 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
650 drvdata->enable_ctrl2 = 0x0;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700651 drvdata->enable_event = 0x6F;
652 drvdata->enable_ctrl1 = 0x1000000;
653 drvdata->fifofull_level = 0x28;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800654 if (drvdata->data_trace_support == true) {
655 drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
656 ETM_MODE_DATA_TRACE_ADDR);
657 drvdata->ctrl |= BIT(2) | BIT(3);
658 drvdata->viewdata_event = 0x6F;
659 drvdata->viewdata_ctrl1 = 0x0;
660 drvdata->viewdata_ctrl3 = 0x10000;
661 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700662 drvdata->addr_idx = 0x0;
663 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
664 drvdata->addr_val[i] = 0x0;
665 drvdata->addr_acctype[i] = 0x0;
666 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800667 }
Pushkar Joshi85688c62012-12-06 10:52:02 -0800668 for (i = 0; i < drvdata->nr_data_cmp; i++) {
669 drvdata->data_val[i] = 0;
670 drvdata->data_mask[i] = ~(0);
671 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700672 drvdata->cntr_idx = 0x0;
673 for (i = 0; i < drvdata->nr_cntr; i++) {
674 drvdata->cntr_rld_val[i] = 0x0;
675 drvdata->cntr_event[i] = 0x406F;
676 drvdata->cntr_rld_event[i] = 0x406F;
677 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800678 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700679 drvdata->seq_12_event = 0x406F;
680 drvdata->seq_21_event = 0x406F;
681 drvdata->seq_23_event = 0x406F;
682 drvdata->seq_31_event = 0x406F;
683 drvdata->seq_32_event = 0x406F;
684 drvdata->seq_13_event = 0x406F;
685 drvdata->seq_curr_state = 0x0;
686 drvdata->ctxid_idx = 0x0;
687 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
688 drvdata->ctxid_val[i] = 0x0;
689 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700690 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
691 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
692 drvdata->sync_freq = 0x100;
693 else
694 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700695 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800696 }
Pratik Patel0a10be22012-10-23 21:12:07 -0700697 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700698 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800699}
Pratik Patela9c0e062012-05-28 13:45:35 -0700700static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800701
Pratik Patela9c0e062012-05-28 13:45:35 -0700702static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
703 char *buf)
704{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700705 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700706 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700707
Pratik Patela9c0e062012-05-28 13:45:35 -0700708 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
709}
710
711static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
712 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800713{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700714 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800715 unsigned long val;
716
717 if (sscanf(buf, "%lx", &val) != 1)
718 return -EINVAL;
719
Pratik Patel0a10be22012-10-23 21:12:07 -0700720 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700721 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800722
Pratik Patel16aefdb2012-05-30 10:41:23 -0700723 if (drvdata->mode & ETM_MODE_EXCLUDE)
724 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800725 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700726 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800727
Pratik Patel16aefdb2012-05-30 10:41:23 -0700728 if (drvdata->mode & ETM_MODE_CYCACC)
729 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800730 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700731 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800732
Pratik Patel16aefdb2012-05-30 10:41:23 -0700733 if (drvdata->mode & ETM_MODE_STALL)
734 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800735 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700736 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800737
Pratik Patel16aefdb2012-05-30 10:41:23 -0700738 if (drvdata->mode & ETM_MODE_TIMESTAMP)
739 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800740 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700741 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700742
Pratik Patel16aefdb2012-05-30 10:41:23 -0700743 if (drvdata->mode & ETM_MODE_CTXID)
744 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800745 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700746 drvdata->ctrl &= ~(BIT(14) | BIT(15));
Pushkar Joshi85688c62012-12-06 10:52:02 -0800747 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
748 if (drvdata->mode & ETM_MODE_DATA_TRACE_VAL)
749 drvdata->ctrl |= BIT(2);
750 else
751 drvdata->ctrl &= ~(BIT(2));
752
753 if (drvdata->mode & ETM_MODE_DATA_TRACE_ADDR)
754 drvdata->ctrl |= (BIT(3));
755 else
756 drvdata->ctrl &= ~(BIT(3));
757 }
Pratik Patel0a10be22012-10-23 21:12:07 -0700758 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800759
Pratik Patela9c0e062012-05-28 13:45:35 -0700760 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800761}
Pratik Patela9c0e062012-05-28 13:45:35 -0700762static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800763
Pratik Patela9c0e062012-05-28 13:45:35 -0700764static ssize_t etm_show_trigger_event(struct device *dev,
765 struct device_attribute *attr, char *buf)
766{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700767 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700768 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700769
Pratik Patela9c0e062012-05-28 13:45:35 -0700770 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
771}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800772
Pratik Patela9c0e062012-05-28 13:45:35 -0700773static ssize_t etm_store_trigger_event(struct device *dev,
774 struct device_attribute *attr,
775 const char *buf, size_t size)
776{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700777 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700778 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800779
Pratik Patela9c0e062012-05-28 13:45:35 -0700780 if (sscanf(buf, "%lx", &val) != 1)
781 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800782
Pratik Patel16aefdb2012-05-30 10:41:23 -0700783 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700784 return size;
785}
786static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
787 etm_store_trigger_event);
788
789static ssize_t etm_show_enable_event(struct device *dev,
790 struct device_attribute *attr, char *buf)
791{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700792 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700793 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700794
Pratik Patela9c0e062012-05-28 13:45:35 -0700795 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
796}
797
798static ssize_t etm_store_enable_event(struct device *dev,
799 struct device_attribute *attr,
800 const char *buf, size_t size)
801{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700802 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700803 unsigned long val;
804
805 if (sscanf(buf, "%lx", &val) != 1)
806 return -EINVAL;
807
Pratik Patel16aefdb2012-05-30 10:41:23 -0700808 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700809 return size;
810}
811static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
812 etm_store_enable_event);
813
814static ssize_t etm_show_fifofull_level(struct device *dev,
815 struct device_attribute *attr, char *buf)
816{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700817 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700818 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700819
Pratik Patela9c0e062012-05-28 13:45:35 -0700820 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
821}
822
823static ssize_t etm_store_fifofull_level(struct device *dev,
824 struct device_attribute *attr,
825 const char *buf, size_t size)
826{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700827 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700828 unsigned long val;
829
830 if (sscanf(buf, "%lx", &val) != 1)
831 return -EINVAL;
832
Pratik Patel16aefdb2012-05-30 10:41:23 -0700833 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700834 return size;
835}
836static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
837 etm_store_fifofull_level);
838
839static ssize_t etm_show_addr_idx(struct device *dev,
840 struct device_attribute *attr, char *buf)
841{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700842 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700843 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700844
Pratik Patela9c0e062012-05-28 13:45:35 -0700845 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
846}
847
848static ssize_t etm_store_addr_idx(struct device *dev,
849 struct device_attribute *attr,
850 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800851{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700852 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800853 unsigned long val;
854
855 if (sscanf(buf, "%lx", &val) != 1)
856 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700857 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800858 return -EINVAL;
859
Pratik Patel0a10be22012-10-23 21:12:07 -0700860 /*
861 * Use spinlock to ensure index doesn't change while it gets
862 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -0800863 */
Pratik Patel0a10be22012-10-23 21:12:07 -0700864 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700865 drvdata->addr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -0700866 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700867 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800868}
Pratik Patela9c0e062012-05-28 13:45:35 -0700869static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
870 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800871
Pratik Patela9c0e062012-05-28 13:45:35 -0700872static ssize_t etm_show_addr_single(struct device *dev,
873 struct device_attribute *attr, char *buf)
874{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700875 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700876 unsigned long val;
877 uint8_t idx;
878
Pratik Patel0a10be22012-10-23 21:12:07 -0700879 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700880 idx = drvdata->addr_idx;
881 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
882 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700883 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700884 return -EPERM;
885 }
886
Pratik Patel16aefdb2012-05-30 10:41:23 -0700887 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700888 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700889 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
890}
891
892static ssize_t etm_store_addr_single(struct device *dev,
893 struct device_attribute *attr,
894 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800895{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700896 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800897 unsigned long val;
898 uint8_t idx;
899
900 if (sscanf(buf, "%lx", &val) != 1)
901 return -EINVAL;
902
Pratik Patel0a10be22012-10-23 21:12:07 -0700903 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700904 idx = drvdata->addr_idx;
905 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
906 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700907 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800908 return -EPERM;
909 }
910
Pratik Patel16aefdb2012-05-30 10:41:23 -0700911 drvdata->addr_val[idx] = val;
912 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
Pushkar Joshi85688c62012-12-06 10:52:02 -0800913 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
914 drvdata->enable_ctrl2 |= (1 << idx);
Pratik Patel0a10be22012-10-23 21:12:07 -0700915 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700916 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800917}
Pratik Patela9c0e062012-05-28 13:45:35 -0700918static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
919 etm_store_addr_single);
920
921static ssize_t etm_show_addr_range(struct device *dev,
922 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800923{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700924 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700925 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800926 uint8_t idx;
927
Pratik Patel0a10be22012-10-23 21:12:07 -0700928 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700929 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700930 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700931 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700932 return -EPERM;
933 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700934 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
935 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
936 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
937 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700938 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800939 return -EPERM;
940 }
941
Pratik Patel16aefdb2012-05-30 10:41:23 -0700942 val1 = drvdata->addr_val[idx];
943 val2 = drvdata->addr_val[idx + 1];
Pratik Patel0a10be22012-10-23 21:12:07 -0700944 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700945 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800946}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800947
Pratik Patela9c0e062012-05-28 13:45:35 -0700948static ssize_t etm_store_addr_range(struct device *dev,
949 struct device_attribute *attr,
950 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800951{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700952 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800953 unsigned long val1, val2;
954 uint8_t idx;
955
956 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
957 return -EINVAL;
958 /* lower address comparator cannot have a higher address value */
959 if (val1 > val2)
960 return -EINVAL;
961
Pratik Patel0a10be22012-10-23 21:12:07 -0700962 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700963 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800964 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700965 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800966 return -EPERM;
967 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700968 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
969 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
970 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
971 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700972 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800973 return -EPERM;
974 }
975
Pratik Patel16aefdb2012-05-30 10:41:23 -0700976 drvdata->addr_val[idx] = val1;
977 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
978 drvdata->addr_val[idx + 1] = val2;
979 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
980 drvdata->enable_ctrl1 |= (1 << (idx/2));
Pratik Patel0a10be22012-10-23 21:12:07 -0700981 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700982 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800983}
Pratik Patela9c0e062012-05-28 13:45:35 -0700984static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
985 etm_store_addr_range);
986
987static ssize_t etm_show_addr_start(struct device *dev,
988 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800989{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700990 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700991 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800992 uint8_t idx;
993
Pratik Patel0a10be22012-10-23 21:12:07 -0700994 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700995 idx = drvdata->addr_idx;
996 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
997 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700998 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800999 return -EPERM;
1000 }
1001
Pratik Patel16aefdb2012-05-30 10:41:23 -07001002 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001003 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001004 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001005}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001006
Pratik Patela9c0e062012-05-28 13:45:35 -07001007static ssize_t etm_store_addr_start(struct device *dev,
1008 struct device_attribute *attr,
1009 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001010{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001011 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001012 unsigned long val;
1013 uint8_t idx;
1014
1015 if (sscanf(buf, "%lx", &val) != 1)
1016 return -EINVAL;
1017
Pratik Patel0a10be22012-10-23 21:12:07 -07001018 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001019 idx = drvdata->addr_idx;
1020 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1021 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001022 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001023 return -EPERM;
1024 }
1025
Pratik Patel16aefdb2012-05-30 10:41:23 -07001026 drvdata->addr_val[idx] = val;
1027 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
1028 drvdata->startstop_ctrl |= (1 << idx);
1029 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -07001030 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001031 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001032}
Pratik Patela9c0e062012-05-28 13:45:35 -07001033static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
1034 etm_store_addr_start);
1035
1036static ssize_t etm_show_addr_stop(struct device *dev,
1037 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001038{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001039 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001040 unsigned long val;
1041 uint8_t idx;
1042
Pratik Patel0a10be22012-10-23 21:12:07 -07001043 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001044 idx = drvdata->addr_idx;
1045 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1046 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001047 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001048 return -EPERM;
1049 }
1050
Pratik Patel16aefdb2012-05-30 10:41:23 -07001051 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001052 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001053 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1054}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001055
Pratik Patela9c0e062012-05-28 13:45:35 -07001056static ssize_t etm_store_addr_stop(struct device *dev,
1057 struct device_attribute *attr,
1058 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001059{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001060 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001061 unsigned long val;
1062 uint8_t idx;
1063
1064 if (sscanf(buf, "%lx", &val) != 1)
1065 return -EINVAL;
1066
Pratik Patel0a10be22012-10-23 21:12:07 -07001067 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001068 idx = drvdata->addr_idx;
1069 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
1070 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -07001071 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001072 return -EPERM;
1073 }
1074
Pratik Patel16aefdb2012-05-30 10:41:23 -07001075 drvdata->addr_val[idx] = val;
1076 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
1077 drvdata->startstop_ctrl |= (1 << (idx + 16));
1078 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -07001079 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001080 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001081}
Pratik Patela9c0e062012-05-28 13:45:35 -07001082static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
1083 etm_store_addr_stop);
1084
1085static ssize_t etm_show_addr_acctype(struct device *dev,
1086 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001087{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001088 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001089 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001090
Pratik Patel0a10be22012-10-23 21:12:07 -07001091 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001092 val = drvdata->addr_acctype[drvdata->addr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001093 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001094 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1095}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001096
Pratik Patela9c0e062012-05-28 13:45:35 -07001097static ssize_t etm_store_addr_acctype(struct device *dev,
1098 struct device_attribute *attr,
1099 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001100{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001101 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001102 unsigned long val;
1103
1104 if (sscanf(buf, "%lx", &val) != 1)
1105 return -EINVAL;
1106
Pratik Patel0a10be22012-10-23 21:12:07 -07001107 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001108 drvdata->addr_acctype[drvdata->addr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001109 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001110 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001111}
Pratik Patela9c0e062012-05-28 13:45:35 -07001112static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
1113 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001114
Pushkar Joshi85688c62012-12-06 10:52:02 -08001115static ssize_t etm_show_data_val(struct device *dev,
1116 struct device_attribute *attr, char *buf)
1117{
1118 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1119 unsigned long val;
1120 uint8_t idx;
1121
1122 spin_lock(&drvdata->spinlock);
1123 idx = drvdata->addr_idx;
1124 if (idx % 2 != 0) {
1125 spin_unlock(&drvdata->spinlock);
1126 return -EPERM;
1127 }
1128 idx = idx >> 1;
1129 if (idx >= drvdata->nr_data_cmp) {
1130 spin_unlock(&drvdata->spinlock);
1131 return -EPERM;
1132 }
1133
1134 val = drvdata->data_val[idx];
1135 spin_unlock(&drvdata->spinlock);
1136 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1137}
1138
1139static ssize_t etm_store_data_val(struct device *dev,
1140 struct device_attribute *attr,
1141 const char *buf, size_t size)
1142{
1143 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1144 unsigned long val;
1145 uint8_t idx, data_idx;
1146
1147 if (sscanf(buf, "%lx", &val) != 1)
1148 return -EINVAL;
1149
1150 spin_lock(&drvdata->spinlock);
1151 idx = drvdata->addr_idx;
1152 /* Adjust index to use the correct data comparator */
1153 data_idx = idx >> 1;
1154 /* Only idx = 0, 2, 4, 6... are valid */
1155 if (idx % 2 != 0) {
1156 spin_unlock(&drvdata->spinlock);
1157 return -EPERM;
1158 }
1159 if (data_idx >= drvdata->nr_data_cmp) {
1160 spin_unlock(&drvdata->spinlock);
1161 return -EPERM;
1162 }
1163 if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
1164 spin_unlock(&drvdata->spinlock);
1165 return -EPERM;
1166 }
1167 if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
1168 if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
1169 spin_unlock(&drvdata->spinlock);
1170 return -EPERM;
1171 }
1172 }
1173
1174 drvdata->data_val[data_idx] = val;
1175 spin_unlock(&drvdata->spinlock);
1176 return size;
1177}
1178static DEVICE_ATTR(data_val, S_IRUGO | S_IWUSR, etm_show_data_val,
1179 etm_store_data_val);
1180
1181static ssize_t etm_show_data_mask(struct device *dev,
1182 struct device_attribute *attr, char *buf)
1183{
1184 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1185 unsigned long mask;
1186 uint8_t idx;
1187
1188 spin_lock(&drvdata->spinlock);
1189 idx = drvdata->addr_idx;
1190 if (idx % 2 != 0) {
1191 spin_unlock(&drvdata->spinlock);
1192 return -EPERM;
1193 }
1194 idx = idx >> 1;
1195 if (idx >= drvdata->nr_data_cmp) {
1196 spin_unlock(&drvdata->spinlock);
1197 return -EPERM;
1198 }
1199
1200 mask = drvdata->data_mask[idx];
1201 spin_unlock(&drvdata->spinlock);
1202 return scnprintf(buf, PAGE_SIZE, "%#lx\n", mask);
1203}
1204
1205static ssize_t etm_store_data_mask(struct device *dev,
1206 struct device_attribute *attr,
1207 const char *buf, size_t size)
1208{
1209 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1210 unsigned long mask;
1211 uint8_t idx, data_idx;
1212
1213 if (sscanf(buf, "%lx", &mask) != 1)
1214 return -EINVAL;
1215
1216 spin_lock(&drvdata->spinlock);
1217 idx = drvdata->addr_idx;
1218 /* Adjust index to use the correct data comparator */
1219 data_idx = idx >> 1;
1220 /* Only idx = 0, 2, 4, 6... are valid */
1221 if (idx % 2 != 0) {
1222 spin_unlock(&drvdata->spinlock);
1223 return -EPERM;
1224 }
1225 if (data_idx >= drvdata->nr_data_cmp) {
1226 spin_unlock(&drvdata->spinlock);
1227 return -EPERM;
1228 }
1229 if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
1230 spin_unlock(&drvdata->spinlock);
1231 return -EPERM;
1232 }
1233 if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
1234 if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
1235 spin_unlock(&drvdata->spinlock);
1236 return -EPERM;
1237 }
1238 }
1239
1240 drvdata->data_mask[data_idx] = mask;
1241 spin_unlock(&drvdata->spinlock);
1242 return size;
1243}
1244static DEVICE_ATTR(data_mask, S_IRUGO | S_IWUSR, etm_show_data_mask,
1245 etm_store_data_mask);
1246
Pratik Patela9c0e062012-05-28 13:45:35 -07001247static ssize_t etm_show_cntr_idx(struct device *dev,
1248 struct device_attribute *attr, char *buf)
1249{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001250 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001251 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001252
Pratik Patel6630ebe2012-03-06 16:44:22 -08001253 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1254}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001255
Pratik Patela9c0e062012-05-28 13:45:35 -07001256static ssize_t etm_store_cntr_idx(struct device *dev,
1257 struct device_attribute *attr,
1258 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001259{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001260 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001261 unsigned long val;
1262
1263 if (sscanf(buf, "%lx", &val) != 1)
1264 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001265 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001266 return -EINVAL;
1267
Pratik Patel0a10be22012-10-23 21:12:07 -07001268 /*
1269 * Use spinlock to ensure index doesn't change while it gets
1270 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001271 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001272 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001273 drvdata->cntr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001274 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001275 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001276}
Pratik Patela9c0e062012-05-28 13:45:35 -07001277static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
1278 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001279
Pratik Patela9c0e062012-05-28 13:45:35 -07001280static ssize_t etm_show_cntr_rld_val(struct device *dev,
1281 struct device_attribute *attr, char *buf)
1282{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001283 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001284 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001285
Pratik Patel0a10be22012-10-23 21:12:07 -07001286 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001287 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001288 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001289 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1290}
1291
1292static ssize_t etm_store_cntr_rld_val(struct device *dev,
1293 struct device_attribute *attr,
1294 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001295{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001296 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001297 unsigned long val;
1298
1299 if (sscanf(buf, "%lx", &val) != 1)
1300 return -EINVAL;
1301
Pratik Patel0a10be22012-10-23 21:12:07 -07001302 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001303 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001304 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001305 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001306}
Pratik Patela9c0e062012-05-28 13:45:35 -07001307static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
1308 etm_store_cntr_rld_val);
1309
1310static ssize_t etm_show_cntr_event(struct device *dev,
1311 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001312{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001313 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001314 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001315
Pratik Patel0a10be22012-10-23 21:12:07 -07001316 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001317 val = drvdata->cntr_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001318 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001319 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1320}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001321
Pratik Patela9c0e062012-05-28 13:45:35 -07001322static ssize_t etm_store_cntr_event(struct device *dev,
1323 struct device_attribute *attr,
1324 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001325{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001326 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001327 unsigned long val;
1328
1329 if (sscanf(buf, "%lx", &val) != 1)
1330 return -EINVAL;
1331
Pratik Patel0a10be22012-10-23 21:12:07 -07001332 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001333 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001334 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001335 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001336}
Pratik Patela9c0e062012-05-28 13:45:35 -07001337static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1338 etm_store_cntr_event);
1339
1340static ssize_t etm_show_cntr_rld_event(struct device *dev,
1341 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001342{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001343 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001344 unsigned long val;
1345
Pratik Patel0a10be22012-10-23 21:12:07 -07001346 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001347 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001348 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001349 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1350}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001351
Pratik Patela9c0e062012-05-28 13:45:35 -07001352static ssize_t etm_store_cntr_rld_event(struct device *dev,
1353 struct device_attribute *attr,
1354 const char *buf, size_t size)
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;
1358
1359 if (sscanf(buf, "%lx", &val) != 1)
1360 return -EINVAL;
1361
Pratik Patel0a10be22012-10-23 21:12:07 -07001362 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001363 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001364 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001365 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001366}
Pratik Patela9c0e062012-05-28 13:45:35 -07001367static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1368 etm_store_cntr_rld_event);
1369
1370static ssize_t etm_show_cntr_val(struct device *dev,
1371 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001372{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001373 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001374 unsigned long val;
1375
Pratik Patel0a10be22012-10-23 21:12:07 -07001376 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001377 val = drvdata->cntr_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001378 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001379 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1380}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001381
Pratik Patela9c0e062012-05-28 13:45:35 -07001382static ssize_t etm_store_cntr_val(struct device *dev,
1383 struct device_attribute *attr,
1384 const char *buf, size_t size)
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
1389 if (sscanf(buf, "%lx", &val) != 1)
1390 return -EINVAL;
1391
Pratik Patel0a10be22012-10-23 21:12:07 -07001392 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001393 drvdata->cntr_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001394 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001395 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001396}
Pratik Patela9c0e062012-05-28 13:45:35 -07001397static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1398 etm_store_cntr_val);
1399
1400static ssize_t etm_show_seq_12_event(struct device *dev,
1401 struct device_attribute *attr, char *buf)
1402{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001403 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001404 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001405
Pratik Patela9c0e062012-05-28 13:45:35 -07001406 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1407}
1408
1409static ssize_t etm_store_seq_12_event(struct device *dev,
1410 struct device_attribute *attr,
1411 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001412{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001413 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001414 unsigned long val;
1415
Pratik Patela9c0e062012-05-28 13:45:35 -07001416 if (sscanf(buf, "%lx", &val) != 1)
1417 return -EINVAL;
1418
Pratik Patel16aefdb2012-05-30 10:41:23 -07001419 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001420 return size;
1421}
1422static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1423 etm_store_seq_12_event);
1424
1425static ssize_t etm_show_seq_21_event(struct device *dev,
1426 struct device_attribute *attr, char *buf)
1427{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001428 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001429 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001430
Pratik Patel6630ebe2012-03-06 16:44:22 -08001431 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1432}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001433
Pratik Patela9c0e062012-05-28 13:45:35 -07001434static ssize_t etm_store_seq_21_event(struct device *dev,
1435 struct device_attribute *attr,
1436 const char *buf, size_t size)
1437{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001438 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001439 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001440
Pratik Patela9c0e062012-05-28 13:45:35 -07001441 if (sscanf(buf, "%lx", &val) != 1)
1442 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001443
Pratik Patel16aefdb2012-05-30 10:41:23 -07001444 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001445 return size;
1446}
1447static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1448 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001449
Pratik Patela9c0e062012-05-28 13:45:35 -07001450static ssize_t etm_show_seq_23_event(struct device *dev,
1451 struct device_attribute *attr, char *buf)
1452{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001453 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001454 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001455
Pratik Patela9c0e062012-05-28 13:45:35 -07001456 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1457}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001458
Pratik Patela9c0e062012-05-28 13:45:35 -07001459static ssize_t etm_store_seq_23_event(struct device *dev,
1460 struct device_attribute *attr,
1461 const char *buf, size_t size)
1462{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001463 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001464 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001465
Pratik Patela9c0e062012-05-28 13:45:35 -07001466 if (sscanf(buf, "%lx", &val) != 1)
1467 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001468
Pratik Patel16aefdb2012-05-30 10:41:23 -07001469 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001470 return size;
1471}
1472static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1473 etm_store_seq_23_event);
1474
1475static ssize_t etm_show_seq_31_event(struct device *dev,
1476 struct device_attribute *attr, char *buf)
1477{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001478 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001479 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001480
Pratik Patela9c0e062012-05-28 13:45:35 -07001481 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1482}
1483
1484static ssize_t etm_store_seq_31_event(struct device *dev,
1485 struct device_attribute *attr,
1486 const char *buf, size_t size)
1487{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001488 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001489 unsigned long val;
1490
1491 if (sscanf(buf, "%lx", &val) != 1)
1492 return -EINVAL;
1493
Pratik Patel16aefdb2012-05-30 10:41:23 -07001494 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001495 return size;
1496}
1497static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1498 etm_store_seq_31_event);
1499
1500static ssize_t etm_show_seq_32_event(struct device *dev,
1501 struct device_attribute *attr, char *buf)
1502{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001503 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001504 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001505
Pratik Patela9c0e062012-05-28 13:45:35 -07001506 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1507}
1508
1509static ssize_t etm_store_seq_32_event(struct device *dev,
1510 struct device_attribute *attr,
1511 const char *buf, size_t size)
1512{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001513 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001514 unsigned long val;
1515
1516 if (sscanf(buf, "%lx", &val) != 1)
1517 return -EINVAL;
1518
Pratik Patel16aefdb2012-05-30 10:41:23 -07001519 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001520 return size;
1521}
1522static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1523 etm_store_seq_32_event);
1524
1525static ssize_t etm_show_seq_13_event(struct device *dev,
1526 struct device_attribute *attr, char *buf)
1527{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001528 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001529 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001530
Pratik Patela9c0e062012-05-28 13:45:35 -07001531 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1532}
1533
1534static ssize_t etm_store_seq_13_event(struct device *dev,
1535 struct device_attribute *attr,
1536 const char *buf, size_t size)
1537{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001538 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001539 unsigned long val;
1540
1541 if (sscanf(buf, "%lx", &val) != 1)
1542 return -EINVAL;
1543
Pratik Patel16aefdb2012-05-30 10:41:23 -07001544 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001545 return size;
1546}
1547static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1548 etm_store_seq_13_event);
1549
1550static ssize_t etm_show_seq_curr_state(struct device *dev,
1551 struct device_attribute *attr, char *buf)
1552{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001553 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001554 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001555
Pratik Patela9c0e062012-05-28 13:45:35 -07001556 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1557}
1558
1559static ssize_t etm_store_seq_curr_state(struct device *dev,
1560 struct device_attribute *attr,
1561 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001562{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001563 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001564 unsigned long val;
1565
1566 if (sscanf(buf, "%lx", &val) != 1)
1567 return -EINVAL;
1568 if (val > ETM_SEQ_STATE_MAX_VAL)
1569 return -EINVAL;
1570
Pratik Patel16aefdb2012-05-30 10:41:23 -07001571 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001572 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001573}
Pratik Patela9c0e062012-05-28 13:45:35 -07001574static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1575 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001576
Pratik Patela9c0e062012-05-28 13:45:35 -07001577static ssize_t etm_show_ctxid_idx(struct device *dev,
1578 struct device_attribute *attr, char *buf)
1579{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001580 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001581 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001582
Pratik Patela9c0e062012-05-28 13:45:35 -07001583 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1584}
1585
1586static ssize_t etm_store_ctxid_idx(struct device *dev,
1587 struct device_attribute *attr,
1588 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001589{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001590 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001591 unsigned long val;
1592
1593 if (sscanf(buf, "%lx", &val) != 1)
1594 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001595 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001596 return -EINVAL;
1597
Pratik Patel0a10be22012-10-23 21:12:07 -07001598 /*
1599 * Use spinlock to ensure index doesn't change while it gets
1600 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001601 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001602 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001603 drvdata->ctxid_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001604 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001605 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001606}
Pratik Patela9c0e062012-05-28 13:45:35 -07001607static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1608 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001609
Pratik Patela9c0e062012-05-28 13:45:35 -07001610static ssize_t etm_show_ctxid_val(struct device *dev,
1611 struct device_attribute *attr, char *buf)
1612{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001613 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001614 unsigned long val;
1615
Pratik Patel0a10be22012-10-23 21:12:07 -07001616 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001617 val = drvdata->ctxid_val[drvdata->ctxid_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001618 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001619 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1620}
1621
1622static ssize_t etm_store_ctxid_val(struct device *dev,
1623 struct device_attribute *attr,
1624 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001625{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001626 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001627 unsigned long val;
1628
1629 if (sscanf(buf, "%lx", &val) != 1)
1630 return -EINVAL;
1631
Pratik Patel0a10be22012-10-23 21:12:07 -07001632 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001633 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001634 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001635 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001636}
Pratik Patela9c0e062012-05-28 13:45:35 -07001637static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1638 etm_store_ctxid_val);
1639
1640static ssize_t etm_show_ctxid_mask(struct device *dev,
1641 struct device_attribute *attr, char *buf)
1642{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001643 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001644 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001645
Pratik Patela9c0e062012-05-28 13:45:35 -07001646 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1647}
1648
1649static ssize_t etm_store_ctxid_mask(struct device *dev,
1650 struct device_attribute *attr,
1651 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001652{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001653 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001654 unsigned long val;
1655
Pratik Patela9c0e062012-05-28 13:45:35 -07001656 if (sscanf(buf, "%lx", &val) != 1)
1657 return -EINVAL;
1658
Pratik Patel16aefdb2012-05-30 10:41:23 -07001659 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001660 return size;
1661}
1662static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1663 etm_store_ctxid_mask);
1664
1665static ssize_t etm_show_sync_freq(struct device *dev,
1666 struct device_attribute *attr, char *buf)
1667{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001668 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001669 unsigned long val = drvdata->sync_freq;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001670
Pratik Patel6630ebe2012-03-06 16:44:22 -08001671 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1672}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001673
Pratik Patela9c0e062012-05-28 13:45:35 -07001674static ssize_t etm_store_sync_freq(struct device *dev,
1675 struct device_attribute *attr,
1676 const char *buf, size_t size)
1677{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001678 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001679 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001680
Pratik Patela9c0e062012-05-28 13:45:35 -07001681 if (sscanf(buf, "%lx", &val) != 1)
1682 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001683
Pratik Patel16aefdb2012-05-30 10:41:23 -07001684 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001685 return size;
1686}
1687static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1688 etm_store_sync_freq);
1689
1690static ssize_t etm_show_timestamp_event(struct device *dev,
1691 struct device_attribute *attr,
1692 char *buf)
1693{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001694 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001695 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001696
Pratik Patela9c0e062012-05-28 13:45:35 -07001697 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1698}
1699
1700static ssize_t etm_store_timestamp_event(struct device *dev,
1701 struct device_attribute *attr,
1702 const char *buf, size_t size)
1703{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001704 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001705 unsigned long val;
1706
1707 if (sscanf(buf, "%lx", &val) != 1)
1708 return -EINVAL;
1709
Pratik Patel16aefdb2012-05-30 10:41:23 -07001710 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001711 return size;
1712}
1713static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1714 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001715
Pratik Patel938e1ff2012-09-28 23:21:46 -07001716static ssize_t etm_show_pcsave(struct device *dev,
1717 struct device_attribute *attr, char *buf)
1718{
1719 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1720 unsigned long val;
1721
1722 val = drvdata->pcsave_enable;
1723 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1724}
1725
Pratik Patelb3354262012-11-30 16:15:46 -08001726static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
Pratik Patel938e1ff2012-09-28 23:21:46 -07001727{
Pratik Patel9dbfa372012-10-23 22:36:40 -07001728 int ret = 0;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001729
1730 ret = clk_prepare_enable(drvdata->clk);
1731 if (ret)
1732 return ret;
1733
Pratik Patel0a10be22012-10-23 21:12:07 -07001734 spin_lock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001735 if (val) {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001736 if (drvdata->pcsave_enable)
1737 goto out;
1738
1739 ret = smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
1740 drvdata, 1);
1741 if (ret)
1742 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001743 drvdata->pcsave_enable = true;
Pratik Patelcd2452e2012-11-15 09:57:29 -08001744 drvdata->pcsave_sticky_enable = true;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001745
1746 dev_info(drvdata->dev, "PC save enabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001747 } else {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001748 if (!drvdata->pcsave_enable)
1749 goto out;
1750
1751 ret = smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
1752 drvdata, 1);
1753 if (ret)
1754 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001755 drvdata->pcsave_enable = false;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001756
1757 dev_info(drvdata->dev, "PC save disabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001758 }
Pratik Patel9dbfa372012-10-23 22:36:40 -07001759out:
Pratik Patel0a10be22012-10-23 21:12:07 -07001760 spin_unlock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001761
1762 clk_disable_unprepare(drvdata->clk);
Pratik Patel9dbfa372012-10-23 22:36:40 -07001763 return ret;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001764}
1765
1766static ssize_t etm_store_pcsave(struct device *dev,
1767 struct device_attribute *attr,
1768 const char *buf, size_t size)
1769{
1770 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1771 unsigned long val;
1772 int ret;
1773
1774 if (sscanf(buf, "%lx", &val) != 1)
1775 return -EINVAL;
1776
1777 ret = __etm_store_pcsave(drvdata, val);
1778 if (ret)
1779 return ret;
1780
1781 return size;
1782}
1783static DEVICE_ATTR(pcsave, S_IRUGO | S_IWUSR, etm_show_pcsave,
1784 etm_store_pcsave);
1785
Pratik Patel6630ebe2012-03-06 16:44:22 -08001786static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001787 &dev_attr_nr_addr_cmp.attr,
1788 &dev_attr_nr_cntr.attr,
1789 &dev_attr_nr_ctxid_cmp.attr,
1790 &dev_attr_reset.attr,
1791 &dev_attr_mode.attr,
1792 &dev_attr_trigger_event.attr,
1793 &dev_attr_enable_event.attr,
1794 &dev_attr_fifofull_level.attr,
1795 &dev_attr_addr_idx.attr,
1796 &dev_attr_addr_single.attr,
1797 &dev_attr_addr_range.attr,
1798 &dev_attr_addr_start.attr,
1799 &dev_attr_addr_stop.attr,
1800 &dev_attr_addr_acctype.attr,
Pushkar Joshi85688c62012-12-06 10:52:02 -08001801 &dev_attr_data_val.attr,
1802 &dev_attr_data_mask.attr,
Pratik Patela9c0e062012-05-28 13:45:35 -07001803 &dev_attr_cntr_idx.attr,
1804 &dev_attr_cntr_rld_val.attr,
1805 &dev_attr_cntr_event.attr,
1806 &dev_attr_cntr_rld_event.attr,
1807 &dev_attr_cntr_val.attr,
1808 &dev_attr_seq_12_event.attr,
1809 &dev_attr_seq_21_event.attr,
1810 &dev_attr_seq_23_event.attr,
1811 &dev_attr_seq_31_event.attr,
1812 &dev_attr_seq_32_event.attr,
1813 &dev_attr_seq_13_event.attr,
1814 &dev_attr_seq_curr_state.attr,
1815 &dev_attr_ctxid_idx.attr,
1816 &dev_attr_ctxid_val.attr,
1817 &dev_attr_ctxid_mask.attr,
1818 &dev_attr_sync_freq.attr,
1819 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001820 NULL,
1821};
1822
1823static struct attribute_group etm_attr_grp = {
1824 .attrs = etm_attrs,
1825};
1826
Pratik Patel3b0ca882012-06-01 16:54:14 -07001827static const struct attribute_group *etm_attr_grps[] = {
1828 &etm_attr_grp,
1829 NULL,
1830};
1831
Pratik Patel97a08f32012-10-22 11:47:41 -07001832static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
1833 void *hcpu)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001834{
Pratik Patel97a08f32012-10-22 11:47:41 -07001835 unsigned int cpu = (unsigned long)hcpu;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001836
Pratik Patelb3354262012-11-30 16:15:46 -08001837 if (!etmdrvdata[cpu])
1838 goto out;
1839
Pratik Patel97a08f32012-10-22 11:47:41 -07001840 switch (action & (~CPU_TASKS_FROZEN)) {
1841 case CPU_STARTING:
Pratik Patelb3354262012-11-30 16:15:46 -08001842 spin_lock(&etmdrvdata[cpu]->spinlock);
1843 if (!etmdrvdata[cpu]->os_unlock) {
Pratik Patel97a08f32012-10-22 11:47:41 -07001844 etm_os_unlock(etmdrvdata[cpu]);
1845 etmdrvdata[cpu]->os_unlock = true;
Pratik Patel97a08f32012-10-22 11:47:41 -07001846 }
1847
Pratik Patelb3354262012-11-30 16:15:46 -08001848 if (etmdrvdata[cpu]->enable)
Pratik Patel97a08f32012-10-22 11:47:41 -07001849 __etm_enable(etmdrvdata[cpu]);
Pratik Patelb3354262012-11-30 16:15:46 -08001850 spin_unlock(&etmdrvdata[cpu]->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -07001851 break;
1852
Pratik Patelcd2452e2012-11-15 09:57:29 -08001853 case CPU_ONLINE:
Pratik Patelb3354262012-11-30 16:15:46 -08001854 if (etmdrvdata[cpu]->pcsave_boot_enable &&
1855 !etmdrvdata[cpu]->pcsave_sticky_enable)
1856 __etm_store_pcsave(etmdrvdata[cpu], 1);
Pratik Patelcd2452e2012-11-15 09:57:29 -08001857 break;
1858
Pratik Patel97a08f32012-10-22 11:47:41 -07001859 case CPU_DYING:
Pratik Patelb3354262012-11-30 16:15:46 -08001860 spin_lock(&etmdrvdata[cpu]->spinlock);
1861 if (etmdrvdata[cpu]->enable)
Pratik Patel97a08f32012-10-22 11:47:41 -07001862 __etm_disable(etmdrvdata[cpu]);
Pratik Patelb3354262012-11-30 16:15:46 -08001863 spin_unlock(&etmdrvdata[cpu]->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -07001864 break;
1865 }
Pratik Patelb3354262012-11-30 16:15:46 -08001866out:
Pratik Patel97a08f32012-10-22 11:47:41 -07001867 return NOTIFY_OK;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001868}
1869
Pratik Patel97a08f32012-10-22 11:47:41 -07001870static struct notifier_block etm_cpu_notifier = {
1871 .notifier_call = etm_cpu_callback,
1872};
1873
Stephen Boyda9510502012-04-24 16:23:34 -07001874static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001875{
Pratik Patel61de7302012-03-07 12:06:10 -08001876 switch (arch) {
1877 case PFT_ARCH_V1_1:
1878 break;
Pushkar Joshi85688c62012-12-06 10:52:02 -08001879 case ETM_ARCH_V3_5:
1880 break;
Pratik Patel61de7302012-03-07 12:06:10 -08001881 default:
1882 return false;
1883 }
1884 return true;
1885}
1886
Pratik Patele6e41da2012-09-12 12:50:29 -07001887static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001888{
Pratik Patel61de7302012-03-07 12:06:10 -08001889 uint32_t etmidr;
1890 uint32_t etmccr;
Pushkar Joshi85688c62012-12-06 10:52:02 -08001891 uint32_t etmcr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001892 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001893
Pratik Patel3b0ca882012-06-01 16:54:14 -07001894 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001895 /*
1896 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
1897 * memory mapped interface and so use it first to enable power/clock
1898 * to allow subsequent cp14 accesses.
1899 */
Pratik Patelef6da292012-09-17 17:37:19 -07001900 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -07001901 /*
1902 * Clear power down bit since when this bit is set writes to
1903 * certain registers might be ignored.
1904 */
1905 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -08001906 etm_clr_pwrup(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001907 /* Set prog bit. It will be set from reset but this is included to
1908 * ensure it is set
1909 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001910 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001911
1912 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001913 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001914 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001915
Pratik Patel3b0ca882012-06-01 16:54:14 -07001916 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001917 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1918 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1919 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1920 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1921 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pushkar Joshi85688c62012-12-06 10:52:02 -08001922 drvdata->nr_data_cmp = BMVAL(etmccr, 4, 7);
1923
1924 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
1925 etmcr = etm_readl(drvdata, ETMCR);
1926 etmcr |= (BIT(2) | BIT(3));
1927 etm_writel(drvdata, etmcr, ETMCR);
1928 etmcr = etm_readl(drvdata, ETMCR);
1929 if (BVAL(etmcr, 2) || BVAL(etmcr, 3))
1930 drvdata->data_trace_support = true;
1931 else
1932 drvdata->data_trace_support = false;
1933 } else
1934 drvdata->data_trace_support = false;
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001935
Pratik Pateld1d65c92012-09-25 23:37:43 -07001936 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001937 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001938}
1939
Pratik Patelc14b4df2012-09-05 18:07:59 -07001940static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1941{
Pratik Patel97a08f32012-10-22 11:47:41 -07001942 drvdata->arch = etmdrvdata[0]->arch;
1943 drvdata->nr_addr_cmp = etmdrvdata[0]->nr_addr_cmp;
1944 drvdata->nr_cntr = etmdrvdata[0]->nr_cntr;
1945 drvdata->nr_ext_inp = etmdrvdata[0]->nr_ext_inp;
1946 drvdata->nr_ext_out = etmdrvdata[0]->nr_ext_out;
1947 drvdata->nr_ctxid_cmp = etmdrvdata[0]->nr_ctxid_cmp;
Pushkar Joshi85688c62012-12-06 10:52:02 -08001948 drvdata->nr_data_cmp = etmdrvdata[0]->nr_data_cmp;
1949 drvdata->data_trace_support = etmdrvdata[0]->data_trace_support;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001950}
1951
Pratik Patel3b0ca882012-06-01 16:54:14 -07001952static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001953{
1954 int i;
1955
1956 drvdata->trigger_event = 0x406F;
1957 drvdata->enable_event = 0x6F;
1958 drvdata->enable_ctrl1 = 0x1;
1959 drvdata->fifofull_level = 0x28;
1960 if (drvdata->nr_addr_cmp >= 2) {
1961 drvdata->addr_val[0] = (uint32_t) _stext;
1962 drvdata->addr_val[1] = (uint32_t) _etext;
1963 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1964 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
Pushkar Joshi85688c62012-12-06 10:52:02 -08001965 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
1966 drvdata->addr_acctype[0] = 0x19;
1967 drvdata->addr_acctype[1] = 0x19;
1968 }
Pratik Patel16aefdb2012-05-30 10:41:23 -07001969 }
1970 for (i = 0; i < drvdata->nr_cntr; i++) {
1971 drvdata->cntr_event[i] = 0x406F;
1972 drvdata->cntr_rld_event[i] = 0x406F;
1973 }
1974 drvdata->seq_12_event = 0x406F;
1975 drvdata->seq_21_event = 0x406F;
1976 drvdata->seq_23_event = 0x406F;
1977 drvdata->seq_31_event = 0x406F;
1978 drvdata->seq_32_event = 0x406F;
1979 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001980 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1981 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1982 drvdata->sync_freq = 0x100;
1983 else
1984 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001985 drvdata->timestamp_event = 0x406F;
1986
1987 /* Overrides for Krait pass1 */
1988 if (cpu_is_krait_v1()) {
1989 /* Krait pass1 doesn't support include filtering and non-cycle
1990 * accurate tracing
1991 */
1992 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1993 drvdata->ctrl = 0x1000;
1994 drvdata->enable_ctrl1 = 0x1000000;
1995 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1996 drvdata->addr_val[i] = 0x0;
1997 drvdata->addr_acctype[i] = 0x0;
1998 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1999 }
2000 }
Pushkar Joshi85688c62012-12-06 10:52:02 -08002001
2002 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
2003 drvdata->ctrl |= BIT(11);
2004 if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
2005 drvdata->enable_ctrl2 = 0x0;
2006 if (drvdata->data_trace_support == true) {
2007 drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
2008 ETM_MODE_DATA_TRACE_ADDR);
2009 drvdata->ctrl |= BIT(2) | BIT(3);
2010 drvdata->viewdata_ctrl1 = 0x0;
2011 drvdata->viewdata_ctrl3 = 0x10000;
2012 drvdata->viewdata_event = 0x6F;
2013 }
2014 for (i = 0; i < drvdata->nr_data_cmp; i++) {
2015 drvdata->data_val[i] = 0;
2016 drvdata->data_mask[i] = ~(0);
2017 }
Pratik Patel16aefdb2012-05-30 10:41:23 -07002018}
2019
Pratik Patel492b3012012-03-06 14:22:30 -08002020static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07002021{
Pratik Patele5771792011-09-17 18:33:54 -07002022 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07002023 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07002024 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002025 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07002026 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07002027 uint32_t reg_size;
2028 static int count;
2029 void *baddr;
2030 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002031 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07002032
Pratik Patel5f6d1af2012-06-13 15:48:13 -07002033 if (pdev->dev.of_node) {
2034 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
2035 if (IS_ERR(pdata))
2036 return PTR_ERR(pdata);
2037 pdev->dev.platform_data = pdata;
2038 }
2039
Pratik Patel4a1b2522012-06-17 15:31:15 -07002040 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
2041 if (!drvdata)
2042 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07002043 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002044 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07002045
Pratik Patel4a1b2522012-06-17 15:31:15 -07002046 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2047 if (!res)
2048 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07002049 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07002050
Pratik Patel4a1b2522012-06-17 15:31:15 -07002051 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
2052 if (!drvdata->base)
2053 return -ENOMEM;
2054
Pratik Patel0a10be22012-10-23 21:12:07 -07002055 spin_lock_init(&drvdata->spinlock);
Pratik Patel3b0ca882012-06-01 16:54:14 -07002056 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07002057
Pratik Patel4a1b2522012-06-17 15:31:15 -07002058 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07002059 if (IS_ERR(drvdata->clk)) {
2060 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07002061 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07002062 }
Pratik Patel2c09b762012-07-21 15:54:54 -07002063
Pratik Patel6fb38342012-06-03 14:51:38 -07002064 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07002065 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07002066 goto err0;
2067
Pratik Patel16aefdb2012-05-30 10:41:23 -07002068 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07002069 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07002070 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07002071
Pratik Patel97a08f32012-10-22 11:47:41 -07002072 drvdata->cpu = count++;
2073
2074 get_online_cpus();
2075 etmdrvdata[drvdata->cpu] = drvdata;
2076
2077 if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, NULL, 1))
2078 drvdata->os_unlock = true;
2079 /*
2080 * Use CPU0 to populate read-only configuration data for ETM0. For
2081 * other ETMs copy it over from ETM0.
Pratik Patelc14b4df2012-09-05 18:07:59 -07002082 */
2083 if (drvdata->cpu == 0) {
Pratik Patel97a08f32012-10-22 11:47:41 -07002084 register_hotcpu_notifier(&etm_cpu_notifier);
2085 if (smp_call_function_single(drvdata->cpu, etm_init_arch_data,
2086 drvdata, 1))
2087 dev_err(dev, "ETM arch init failed\n");
Pratik Patelc14b4df2012-09-05 18:07:59 -07002088 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07002089 etm_copy_arch_data(drvdata);
2090 }
Pratik Patel97a08f32012-10-22 11:47:41 -07002091
2092 put_online_cpus();
2093
Pratik Pateldc3a0a42012-09-11 17:48:23 -07002094 if (etm_arch_supported(drvdata->arch) == false) {
2095 ret = -EINVAL;
2096 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07002097 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07002098 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07002099
Pratik Patel16aefdb2012-05-30 10:41:23 -07002100 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07002101
Pratik Patel26477792012-09-07 01:35:36 -07002102 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
2103 if (baddr) {
2104 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
2105 dump.id = MSM_ETM0_REG + drvdata->cpu;
2106 dump.start_addr = virt_to_phys(baddr);
2107 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
2108 ret = msm_dump_table_register(&dump);
2109 if (ret) {
2110 devm_kfree(dev, baddr);
Pratik Patel97a08f32012-10-22 11:47:41 -07002111 dev_err(dev, "ETM REG dump setup failed/unsupported\n");
Pratik Patel26477792012-09-07 01:35:36 -07002112 }
2113 } else {
2114 dev_err(dev, "ETM REG dump space allocation failed\n");
2115 }
2116
Pratik Patel4a1b2522012-06-17 15:31:15 -07002117 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07002118 if (!desc) {
2119 ret = -ENOMEM;
Pratik Patel97a08f32012-10-22 11:47:41 -07002120 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002121 }
2122 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
2123 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
2124 desc->ops = &etm_cs_ops;
2125 desc->pdata = pdev->dev.platform_data;
2126 desc->dev = &pdev->dev;
2127 desc->groups = etm_attr_grps;
2128 desc->owner = THIS_MODULE;
2129 drvdata->csdev = coresight_register(desc);
2130 if (IS_ERR(drvdata->csdev)) {
2131 ret = PTR_ERR(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07002132 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07002133 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07002134
Pratik Patel938e1ff2012-09-28 23:21:46 -07002135 if (pdev->dev.of_node)
2136 drvdata->pcsave_impl = of_property_read_bool(pdev->dev.of_node,
2137 "qcom,pc-save");
2138 if (drvdata->pcsave_impl) {
2139 ret = device_create_file(&drvdata->csdev->dev,
2140 &dev_attr_pcsave);
2141 if (ret)
2142 dev_err(dev, "ETM pcsave dev node creation failed\n");
2143 }
2144
Pratik Patel4a1b2522012-06-17 15:31:15 -07002145 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07002146
Pratik Patel3b0ca882012-06-01 16:54:14 -07002147 if (boot_enable)
2148 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07002149
Pratik Patelcd2452e2012-11-15 09:57:29 -08002150 if (drvdata->pcsave_impl && boot_pcsave_enable) {
2151 __etm_store_pcsave(drvdata, 1);
2152 drvdata->pcsave_boot_enable = true;
2153 }
Pratik Patel938e1ff2012-09-28 23:21:46 -07002154
Pratik Patel7831c082011-06-08 21:44:37 -07002155 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -07002156err2:
2157 if (drvdata->cpu == 0)
2158 unregister_hotcpu_notifier(&etm_cpu_notifier);
2159 wake_lock_destroy(&drvdata->wake_lock);
2160 return ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07002161err1:
Pratik Patel97a08f32012-10-22 11:47:41 -07002162 if (drvdata->cpu == 0)
2163 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07002164 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07002165err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07002166 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07002167 return ret;
2168}
2169
Pratik Patelf6fe9182012-03-20 14:04:18 -07002170static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07002171{
Pratik Patel3b0ca882012-06-01 16:54:14 -07002172 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
2173
Pratik Patel938e1ff2012-09-28 23:21:46 -07002174 device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
Pratik Patel3b0ca882012-06-01 16:54:14 -07002175 coresight_unregister(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07002176 if (drvdata->cpu == 0)
2177 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07002178 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07002179 return 0;
2180}
2181
Pratik Patel9eae4822012-05-14 17:34:53 -07002182static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07002183 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07002184 {}
2185};
2186
Pratik Patel492b3012012-03-06 14:22:30 -08002187static struct platform_driver etm_driver = {
2188 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07002189 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07002190 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07002191 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07002192 .owner = THIS_MODULE,
2193 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07002194 },
2195};
2196
Pratik Patel492b3012012-03-06 14:22:30 -08002197int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07002198{
Pratik Patel492b3012012-03-06 14:22:30 -08002199 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07002200}
Pratik Patelf6fe9182012-03-20 14:04:18 -07002201module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07002202
Pratik Patelf6fe9182012-03-20 14:04:18 -07002203void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07002204{
Pratik Patel492b3012012-03-06 14:22:30 -08002205 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07002206}
Pratik Patelf6fe9182012-03-20 14:04:18 -07002207module_exit(etm_exit);
2208
2209MODULE_LICENSE("GPL v2");
2210MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");