blob: bb24ff979917cce1877262a7e81335b951dada51 [file] [log] [blame]
Pratik Patelef6da292012-09-17 17:37:19 -07001/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
Pratik Patel7831c082011-06-08 21:44:37 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
Pratik Patelcf418622011-09-22 11:15:11 -070015#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/device.h>
Pratik Patel7831c082011-06-08 21:44:37 -070018#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/err.h>
21#include <linux/fs.h>
Pratik Patel7831c082011-06-08 21:44:37 -070022#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/smp.h>
Pratik Patel7831c082011-06-08 21:44:37 -070025#include <linux/wakelock.h>
Pratik Patel6630ebe2012-03-06 16:44:22 -080026#include <linux/sysfs.h>
27#include <linux/stat.h>
Pratik Patel3b0ca882012-06-01 16:54:14 -070028#include <linux/mutex.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070029#include <linux/clk.h>
Pratik Patel5f6d1af2012-06-13 15:48:13 -070030#include <linux/of_coresight.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070031#include <linux/coresight.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080032#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080033#include <mach/socinfo.h>
Pratik Patel26477792012-09-07 01:35:36 -070034#include <mach/msm_memory_dump.h>
Pratik Patel7831c082011-06-08 21:44:37 -070035
Pratik Patel1746b8f2012-06-02 21:11:41 -070036#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070037
Pratik Patele6e41da2012-09-12 12:50:29 -070038#define etm_writel_mm(drvdata, val, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070039 __raw_writel((val), drvdata->base + off)
Pratik Patele6e41da2012-09-12 12:50:29 -070040#define etm_readl_mm(drvdata, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070041 __raw_readl(drvdata->base + off)
42
Pratik Patele6e41da2012-09-12 12:50:29 -070043#define etm_writel(drvdata, val, off) \
44({ \
45 if (cpu_is_krait_v3()) \
46 etm_writel_cp14(val, off); \
47 else \
48 etm_writel_mm(drvdata, val, off); \
49})
50#define etm_readl(drvdata, off) \
51({ \
52 uint32_t val; \
53 if (cpu_is_krait_v3()) \
54 val = etm_readl_cp14(off); \
55 else \
56 val = etm_readl_mm(drvdata, off); \
57 val; \
58})
59
Pratik Patel3b0ca882012-06-01 16:54:14 -070060#define ETM_LOCK(drvdata) \
61do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070062 /* recommended by spec to ensure ETM writes are committed prior
63 * to resuming execution
64 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070065 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070066 isb(); \
67 etm_writel_mm(drvdata, 0x0, CORESIGHT_LAR); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070068} while (0)
69#define ETM_UNLOCK(drvdata) \
70do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070071 etm_writel_mm(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
72 /* ensure unlock and any pending writes are committed prior to
73 * programming ETM registers
74 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070075 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070076 isb(); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070077} while (0)
78
Pratik Patel7831c082011-06-08 21:44:37 -070079/*
80 * Device registers:
81 * 0x000 - 0x2FC: Trace registers
82 * 0x300 - 0x314: Management registers
83 * 0x318 - 0xEFC: Trace registers
84 *
85 * Coresight registers
86 * 0xF00 - 0xF9C: Management registers
87 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
88 * Trace registers in PFTv1.1
89 * 0xFA8 - 0xFFC: Management registers
90 */
91
92/* Trace registers (0x000-0x2FC) */
93#define ETMCR (0x000)
94#define ETMCCR (0x004)
95#define ETMTRIGGER (0x008)
96#define ETMSR (0x010)
97#define ETMSCR (0x014)
98#define ETMTSSCR (0x018)
99#define ETMTEEVR (0x020)
100#define ETMTECR1 (0x024)
101#define ETMFFLR (0x02C)
102#define ETMACVRn(n) (0x040 + (n * 4))
103#define ETMACTRn(n) (0x080 + (n * 4))
104#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
105#define ETMCNTENRn(n) (0x150 + (n * 4))
106#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
107#define ETMCNTVRn(n) (0x170 + (n * 4))
108#define ETMSQ12EVR (0x180)
109#define ETMSQ21EVR (0x184)
110#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800111#define ETMSQ31EVR (0x18C)
112#define ETMSQ32EVR (0x190)
113#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -0700114#define ETMSQR (0x19C)
115#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
116#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
117#define ETMCIDCMR (0x1BC)
118#define ETMIMPSPEC0 (0x1C0)
119#define ETMIMPSPEC1 (0x1C4)
120#define ETMIMPSPEC2 (0x1C8)
121#define ETMIMPSPEC3 (0x1CC)
122#define ETMIMPSPEC4 (0x1D0)
123#define ETMIMPSPEC5 (0x1D4)
124#define ETMIMPSPEC6 (0x1D8)
125#define ETMIMPSPEC7 (0x1DC)
126#define ETMSYNCFR (0x1E0)
127#define ETMIDR (0x1E4)
128#define ETMCCER (0x1E8)
129#define ETMEXTINSELR (0x1EC)
130#define ETMTESSEICR (0x1F0)
131#define ETMEIBCR (0x1F4)
132#define ETMTSEVR (0x1F8)
133#define ETMAUXCR (0x1FC)
134#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800135#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700136/* Management registers (0x300-0x314) */
137#define ETMOSLAR (0x300)
138#define ETMOSLSR (0x304)
139#define ETMOSSRR (0x308)
140#define ETMPDCR (0x310)
141#define ETMPDSR (0x314)
142
Pratik Patel61de7302012-03-07 12:06:10 -0800143#define ETM_MAX_ADDR_CMP (16)
144#define ETM_MAX_CNTR (4)
145#define ETM_MAX_CTXID_CMP (3)
146
Pratik Patel6630ebe2012-03-06 16:44:22 -0800147#define ETM_MODE_EXCLUDE BIT(0)
148#define ETM_MODE_CYCACC BIT(1)
149#define ETM_MODE_STALL BIT(2)
150#define ETM_MODE_TIMESTAMP BIT(3)
151#define ETM_MODE_CTXID BIT(4)
152#define ETM_MODE_ALL (0x1F)
153
154#define ETM_EVENT_MASK (0x1FFFF)
155#define ETM_SYNC_MASK (0xFFF)
156#define ETM_ALL_MASK (0xFFFFFFFF)
157
158#define ETM_SEQ_STATE_MAX_VAL (0x2)
159
Pratik Patel26477792012-09-07 01:35:36 -0700160#define ETM_REG_DUMP_VER_OFF (4)
161#define ETM_REG_DUMP_VER (1)
162
Pratik Patel3b0ca882012-06-01 16:54:14 -0700163enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800164 ETM_ADDR_TYPE_NONE,
165 ETM_ADDR_TYPE_SINGLE,
166 ETM_ADDR_TYPE_RANGE,
167 ETM_ADDR_TYPE_START,
168 ETM_ADDR_TYPE_STOP,
169};
170
Pratik Patel29cba152012-01-03 11:40:26 -0800171#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700172static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800173#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700174static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800175#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700176module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700177 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700178);
179
Pratik Patel16aefdb2012-05-30 10:41:23 -0700180struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700181 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700182 struct device *dev;
183 struct coresight_device *csdev;
184 struct clk *clk;
185 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700186 struct wake_lock wake_lock;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700187 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800188 uint8_t arch;
189 uint8_t nr_addr_cmp;
190 uint8_t nr_cntr;
191 uint8_t nr_ext_inp;
192 uint8_t nr_ext_out;
193 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800194 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800195 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800196 uint32_t ctrl;
197 uint32_t trigger_event;
198 uint32_t startstop_ctrl;
199 uint32_t enable_event;
200 uint32_t enable_ctrl1;
201 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800202 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800203 uint32_t addr_val[ETM_MAX_ADDR_CMP];
204 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800205 uint32_t addr_type[ETM_MAX_ADDR_CMP];
206 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800207 uint32_t cntr_rld_val[ETM_MAX_CNTR];
208 uint32_t cntr_event[ETM_MAX_CNTR];
209 uint32_t cntr_rld_event[ETM_MAX_CNTR];
210 uint32_t cntr_val[ETM_MAX_CNTR];
211 uint32_t seq_12_event;
212 uint32_t seq_21_event;
213 uint32_t seq_23_event;
214 uint32_t seq_31_event;
215 uint32_t seq_32_event;
216 uint32_t seq_13_event;
217 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800218 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800219 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
220 uint32_t ctxid_mask;
221 uint32_t sync_freq;
222 uint32_t timestamp_event;
Pratik Patel7831c082011-06-08 21:44:37 -0700223};
224
Pratik Patelc14b4df2012-09-05 18:07:59 -0700225static struct etm_drvdata *etm0drvdata;
226
Pratik Pateld1d65c92012-09-25 23:37:43 -0700227/*
228 * ETM clock is derived from the processor clock and gets enabled on a
229 * logical OR of below items on Krait (v2 onwards):
Pratik Patel17f3b822011-11-21 12:41:47 -0800230 * 1.CPMR[ETMCLKEN] is 1
231 * 2.ETMCR[PD] is 0
232 * 3.ETMPDCR[PU] is 1
233 * 4.Reset is asserted (core or debug)
234 * 5.APB memory mapped requests (eg. EDAP access)
235 *
236 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
237 * enables
238 *
Pratik Pateld1d65c92012-09-25 23:37:43 -0700239 * We rely on 5. to be able to access ETMCR/ETMPDCR and then use 2./3. above
240 * for ETM clock vote in the driver and the save-restore code uses 1. above
Pratik Patel17f3b822011-11-21 12:41:47 -0800241 * for its vote
242 */
Pratik Pateld1d65c92012-09-25 23:37:43 -0700243static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
244{
245 uint32_t etmcr;
246
247 /* ensure pending cp14 accesses complete before setting pwrdwn */
248 mb();
249 isb();
250 etmcr = etm_readl(drvdata, ETMCR);
251 etmcr |= BIT(0);
252 etm_writel(drvdata, etmcr, ETMCR);
253}
254
255static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
256{
257 uint32_t etmcr;
258
259 etmcr = etm_readl(drvdata, ETMCR);
260 etmcr &= ~BIT(0);
261 etm_writel(drvdata, etmcr, ETMCR);
262 /* ensure pwrup completes before subsequent cp14 accesses */
263 mb();
264 isb();
265}
266
Pratik Patelef6da292012-09-17 17:37:19 -0700267static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700268{
Pratik Patelef6da292012-09-17 17:37:19 -0700269 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700270
Pratik Patele6e41da2012-09-12 12:50:29 -0700271 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700272 etmpdcr |= BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700273 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
274 /* ensure pwrup completes before subsequent cp14 accesses */
275 mb();
276 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700277}
278
Pratik Patelef6da292012-09-17 17:37:19 -0700279static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700280{
Pratik Patelef6da292012-09-17 17:37:19 -0700281 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700282
Pratik Patele6e41da2012-09-12 12:50:29 -0700283 /* ensure pending cp14 accesses complete before clearing pwrup */
284 mb();
285 isb();
286 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700287 etmpdcr &= ~BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700288 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700289}
290
Pratik Patel3b0ca882012-06-01 16:54:14 -0700291static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700292{
293 uint32_t etmcr;
294 int count;
295
Pratik Patel3b0ca882012-06-01 16:54:14 -0700296 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700297 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700298 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700299 /* recommended by spec for cp14 accesses to ensure etmcr write is
300 * complete before polling etmsr
301 */
302 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700303 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700304 && count > 0; count--)
305 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800306 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700307 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700308}
309
Pratik Patel3b0ca882012-06-01 16:54:14 -0700310static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700311{
312 uint32_t etmcr;
313 int count;
314
Pratik Patel3b0ca882012-06-01 16:54:14 -0700315 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700316 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700317 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700318 /* recommended by spec for cp14 accesses to ensure etmcr write is
319 * complete before polling etmsr
320 */
321 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700322 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700323 && count > 0; count--)
324 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800325 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700326 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700327}
328
Pratik Patel66e1a412012-09-06 11:07:06 -0700329static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700330{
Pratik Patel17f3b822011-11-21 12:41:47 -0800331 int i;
Pratik Pateld1d65c92012-09-25 23:37:43 -0700332 uint32_t etmcr;
Pratik Patel66e1a412012-09-06 11:07:06 -0700333 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700334
Pratik Patel3b0ca882012-06-01 16:54:14 -0700335 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800336 /* Vote for ETM power/clock enable */
Pratik Patelef6da292012-09-17 17:37:19 -0700337 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -0700338 /*
339 * Clear power down bit since when this bit is set writes to
340 * certain registers might be ignored.
341 */
342 etm_clr_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700343 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700344
Pratik Pateld1d65c92012-09-25 23:37:43 -0700345 etmcr = etm_readl(drvdata, ETMCR);
346 etmcr &= (BIT(10) | BIT(0));
347 etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700348 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
349 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
350 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
351 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
352 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700353 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700354 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
355 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700356 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700357 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700358 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
359 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
360 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700361 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700362 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800363 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700364 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
365 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
366 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
367 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
368 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
369 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
370 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700371 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700372 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700373 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700374 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
375 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
376 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
377 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
378 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
379 etm_writel(drvdata, 0x00000000, ETMAUXCR);
380 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
381 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800382
Pratik Patel3b0ca882012-06-01 16:54:14 -0700383 etm_clr_prog(drvdata);
384 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700385
386 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700387}
388
Pratik Patel3b0ca882012-06-01 16:54:14 -0700389static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700390{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700391 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
392 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800393
Pratik Patel16aefdb2012-05-30 10:41:23 -0700394 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700395
Pratik Patel16aefdb2012-05-30 10:41:23 -0700396 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700397 if (ret)
398 goto err_clk;
399
Pratik Patel3b0ca882012-06-01 16:54:14 -0700400 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700401 /* executing __etm_enable on the cpu whose ETM is being enabled
402 * ensures that register writes occur when cpu is powered.
403 */
404 smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700405 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700406
Pratik Patel16aefdb2012-05-30 10:41:23 -0700407 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700408
Pratik Patel16aefdb2012-05-30 10:41:23 -0700409 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700410 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700411err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700412 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800413 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700414}
415
Pratik Patel66e1a412012-09-06 11:07:06 -0700416static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700417{
Pratik Patel66e1a412012-09-06 11:07:06 -0700418 struct etm_drvdata *drvdata = info;
419
Pratik Patel3b0ca882012-06-01 16:54:14 -0700420 ETM_UNLOCK(drvdata);
421 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700422
Pratik Patel17f3b822011-11-21 12:41:47 -0800423 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700424 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700425
Pratik Pateld1d65c92012-09-25 23:37:43 -0700426 etm_set_pwrdwn(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800427 /* Vote for ETM power/clock disable */
Pratik Patelef6da292012-09-17 17:37:19 -0700428 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700429 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700430
431 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700432}
433
Pratik Patel3b0ca882012-06-01 16:54:14 -0700434static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700435{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700436 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800437
Pratik Patel16aefdb2012-05-30 10:41:23 -0700438 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700439
Pratik Patel3b0ca882012-06-01 16:54:14 -0700440 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700441 /* executing __etm_disable on the cpu whose ETM is being disabled
442 * ensures that register writes occur when cpu is powered.
443 */
444 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700445 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700446
Pratik Patel16aefdb2012-05-30 10:41:23 -0700447 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700448
Pratik Patel16aefdb2012-05-30 10:41:23 -0700449 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700450
Pratik Patel16aefdb2012-05-30 10:41:23 -0700451 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700452}
453
Pratik Patel3b0ca882012-06-01 16:54:14 -0700454static const struct coresight_ops_source etm_source_ops = {
455 .enable = etm_enable,
456 .disable = etm_disable,
457};
Pratik Patel17f3b822011-11-21 12:41:47 -0800458
Pratik Patel3b0ca882012-06-01 16:54:14 -0700459static const struct coresight_ops etm_cs_ops = {
460 .source_ops = &etm_source_ops,
461};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800462
Pratik Patela9c0e062012-05-28 13:45:35 -0700463static ssize_t etm_show_nr_addr_cmp(struct device *dev,
464 struct device_attribute *attr, char *buf)
465{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700466 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700467 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700468
Pratik Patela9c0e062012-05-28 13:45:35 -0700469 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
470}
471static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
472
473static ssize_t etm_show_nr_cntr(struct device *dev,
474 struct device_attribute *attr, char *buf)
475{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700476 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700477 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700478
Pratik Patela9c0e062012-05-28 13:45:35 -0700479 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
480}
481static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
482
483static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
484 struct device_attribute *attr, char *buf)
485{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700486 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700487 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700488
Pratik Patela9c0e062012-05-28 13:45:35 -0700489 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
490}
491static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
492
493static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
494 char *buf)
495{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700496 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700497 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700498
Pratik Patela9c0e062012-05-28 13:45:35 -0700499 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
500}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800501
Pratik Pateld30deda2012-02-01 14:40:55 -0800502/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700503static ssize_t etm_store_reset(struct device *dev,
504 struct device_attribute *attr, const char *buf,
505 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800506{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700507 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800508 int i;
509 unsigned long val;
510
511 if (sscanf(buf, "%lx", &val) != 1)
512 return -EINVAL;
513
Pratik Patel16aefdb2012-05-30 10:41:23 -0700514 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800515 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700516 drvdata->mode = ETM_MODE_EXCLUDE;
517 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800518 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700519 drvdata->mode |= ETM_MODE_CYCACC;
520 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800521 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700522 drvdata->trigger_event = 0x406F;
523 drvdata->startstop_ctrl = 0x0;
524 drvdata->enable_event = 0x6F;
525 drvdata->enable_ctrl1 = 0x1000000;
526 drvdata->fifofull_level = 0x28;
527 drvdata->addr_idx = 0x0;
528 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
529 drvdata->addr_val[i] = 0x0;
530 drvdata->addr_acctype[i] = 0x0;
531 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800532 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700533 drvdata->cntr_idx = 0x0;
534 for (i = 0; i < drvdata->nr_cntr; i++) {
535 drvdata->cntr_rld_val[i] = 0x0;
536 drvdata->cntr_event[i] = 0x406F;
537 drvdata->cntr_rld_event[i] = 0x406F;
538 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800539 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700540 drvdata->seq_12_event = 0x406F;
541 drvdata->seq_21_event = 0x406F;
542 drvdata->seq_23_event = 0x406F;
543 drvdata->seq_31_event = 0x406F;
544 drvdata->seq_32_event = 0x406F;
545 drvdata->seq_13_event = 0x406F;
546 drvdata->seq_curr_state = 0x0;
547 drvdata->ctxid_idx = 0x0;
548 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
549 drvdata->ctxid_val[i] = 0x0;
550 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700551 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
552 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
553 drvdata->sync_freq = 0x100;
554 else
555 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700556 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800557 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700558 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700559 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800560}
Pratik Patela9c0e062012-05-28 13:45:35 -0700561static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800562
Pratik Patela9c0e062012-05-28 13:45:35 -0700563static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
564 char *buf)
565{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700566 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700567 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700568
Pratik Patela9c0e062012-05-28 13:45:35 -0700569 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
570}
571
572static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
573 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800574{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700575 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800576 unsigned long val;
577
578 if (sscanf(buf, "%lx", &val) != 1)
579 return -EINVAL;
580
Pratik Patel16aefdb2012-05-30 10:41:23 -0700581 mutex_lock(&drvdata->mutex);
582 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800583
Pratik Patel16aefdb2012-05-30 10:41:23 -0700584 if (drvdata->mode & ETM_MODE_EXCLUDE)
585 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800586 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700587 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800588
Pratik Patel16aefdb2012-05-30 10:41:23 -0700589 if (drvdata->mode & ETM_MODE_CYCACC)
590 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800591 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700592 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800593
Pratik Patel16aefdb2012-05-30 10:41:23 -0700594 if (drvdata->mode & ETM_MODE_STALL)
595 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800596 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700597 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800598
Pratik Patel16aefdb2012-05-30 10:41:23 -0700599 if (drvdata->mode & ETM_MODE_TIMESTAMP)
600 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800601 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700602 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700603
Pratik Patel16aefdb2012-05-30 10:41:23 -0700604 if (drvdata->mode & ETM_MODE_CTXID)
605 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800606 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700607 drvdata->ctrl &= ~(BIT(14) | BIT(15));
608 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800609
Pratik Patela9c0e062012-05-28 13:45:35 -0700610 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800611}
Pratik Patela9c0e062012-05-28 13:45:35 -0700612static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800613
Pratik Patela9c0e062012-05-28 13:45:35 -0700614static ssize_t etm_show_trigger_event(struct device *dev,
615 struct device_attribute *attr, char *buf)
616{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700617 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700618 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700619
Pratik Patela9c0e062012-05-28 13:45:35 -0700620 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
621}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800622
Pratik Patela9c0e062012-05-28 13:45:35 -0700623static ssize_t etm_store_trigger_event(struct device *dev,
624 struct device_attribute *attr,
625 const char *buf, size_t size)
626{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700627 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700628 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800629
Pratik Patela9c0e062012-05-28 13:45:35 -0700630 if (sscanf(buf, "%lx", &val) != 1)
631 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800632
Pratik Patel16aefdb2012-05-30 10:41:23 -0700633 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700634 return size;
635}
636static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
637 etm_store_trigger_event);
638
639static ssize_t etm_show_enable_event(struct device *dev,
640 struct device_attribute *attr, char *buf)
641{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700642 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700643 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700644
Pratik Patela9c0e062012-05-28 13:45:35 -0700645 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
646}
647
648static ssize_t etm_store_enable_event(struct device *dev,
649 struct device_attribute *attr,
650 const char *buf, size_t size)
651{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700652 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700653 unsigned long val;
654
655 if (sscanf(buf, "%lx", &val) != 1)
656 return -EINVAL;
657
Pratik Patel16aefdb2012-05-30 10:41:23 -0700658 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700659 return size;
660}
661static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
662 etm_store_enable_event);
663
664static ssize_t etm_show_fifofull_level(struct device *dev,
665 struct device_attribute *attr, char *buf)
666{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700667 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700668 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700669
Pratik Patela9c0e062012-05-28 13:45:35 -0700670 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
671}
672
673static ssize_t etm_store_fifofull_level(struct device *dev,
674 struct device_attribute *attr,
675 const char *buf, size_t size)
676{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700677 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700678 unsigned long val;
679
680 if (sscanf(buf, "%lx", &val) != 1)
681 return -EINVAL;
682
Pratik Patel16aefdb2012-05-30 10:41:23 -0700683 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700684 return size;
685}
686static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
687 etm_store_fifofull_level);
688
689static ssize_t etm_show_addr_idx(struct device *dev,
690 struct device_attribute *attr, char *buf)
691{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700692 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700693 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700694
Pratik Patela9c0e062012-05-28 13:45:35 -0700695 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
696}
697
698static ssize_t etm_store_addr_idx(struct device *dev,
699 struct device_attribute *attr,
700 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800701{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700702 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800703 unsigned long val;
704
705 if (sscanf(buf, "%lx", &val) != 1)
706 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700707 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800708 return -EINVAL;
709
710 /* Use mutex to ensure index doesn't change while it gets dereferenced
711 * multiple times within a mutex block elsewhere.
712 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700713 mutex_lock(&drvdata->mutex);
714 drvdata->addr_idx = val;
715 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700716 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800717}
Pratik Patela9c0e062012-05-28 13:45:35 -0700718static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
719 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800720
Pratik Patela9c0e062012-05-28 13:45:35 -0700721static ssize_t etm_show_addr_single(struct device *dev,
722 struct device_attribute *attr, char *buf)
723{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700724 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700725 unsigned long val;
726 uint8_t idx;
727
Pratik Patel16aefdb2012-05-30 10:41:23 -0700728 mutex_lock(&drvdata->mutex);
729 idx = drvdata->addr_idx;
730 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
731 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
732 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700733 return -EPERM;
734 }
735
Pratik Patel16aefdb2012-05-30 10:41:23 -0700736 val = drvdata->addr_val[idx];
737 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700738 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
739}
740
741static ssize_t etm_store_addr_single(struct device *dev,
742 struct device_attribute *attr,
743 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800744{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700745 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800746 unsigned long val;
747 uint8_t idx;
748
749 if (sscanf(buf, "%lx", &val) != 1)
750 return -EINVAL;
751
Pratik Patel16aefdb2012-05-30 10:41:23 -0700752 mutex_lock(&drvdata->mutex);
753 idx = drvdata->addr_idx;
754 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
755 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
756 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800757 return -EPERM;
758 }
759
Pratik Patel16aefdb2012-05-30 10:41:23 -0700760 drvdata->addr_val[idx] = val;
761 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
762 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700763 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800764}
Pratik Patela9c0e062012-05-28 13:45:35 -0700765static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
766 etm_store_addr_single);
767
768static ssize_t etm_show_addr_range(struct device *dev,
769 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800770{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700771 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700772 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800773 uint8_t idx;
774
Pratik Patel16aefdb2012-05-30 10:41:23 -0700775 mutex_lock(&drvdata->mutex);
776 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700777 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700778 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700779 return -EPERM;
780 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700781 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
782 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
783 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
784 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
785 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800786 return -EPERM;
787 }
788
Pratik Patel16aefdb2012-05-30 10:41:23 -0700789 val1 = drvdata->addr_val[idx];
790 val2 = drvdata->addr_val[idx + 1];
791 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700792 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800793}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800794
Pratik Patela9c0e062012-05-28 13:45:35 -0700795static ssize_t etm_store_addr_range(struct device *dev,
796 struct device_attribute *attr,
797 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800798{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700799 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800800 unsigned long val1, val2;
801 uint8_t idx;
802
803 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
804 return -EINVAL;
805 /* lower address comparator cannot have a higher address value */
806 if (val1 > val2)
807 return -EINVAL;
808
Pratik Patel16aefdb2012-05-30 10:41:23 -0700809 mutex_lock(&drvdata->mutex);
810 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800811 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700812 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800813 return -EPERM;
814 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700815 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
816 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
817 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
818 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
819 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800820 return -EPERM;
821 }
822
Pratik Patel16aefdb2012-05-30 10:41:23 -0700823 drvdata->addr_val[idx] = val1;
824 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
825 drvdata->addr_val[idx + 1] = val2;
826 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
827 drvdata->enable_ctrl1 |= (1 << (idx/2));
828 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700829 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800830}
Pratik Patela9c0e062012-05-28 13:45:35 -0700831static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
832 etm_store_addr_range);
833
834static ssize_t etm_show_addr_start(struct device *dev,
835 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800836{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700837 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700838 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800839 uint8_t idx;
840
Pratik Patel16aefdb2012-05-30 10:41:23 -0700841 mutex_lock(&drvdata->mutex);
842 idx = drvdata->addr_idx;
843 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
844 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
845 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800846 return -EPERM;
847 }
848
Pratik Patel16aefdb2012-05-30 10:41:23 -0700849 val = drvdata->addr_val[idx];
850 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700851 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800852}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800853
Pratik Patela9c0e062012-05-28 13:45:35 -0700854static ssize_t etm_store_addr_start(struct device *dev,
855 struct device_attribute *attr,
856 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800857{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700858 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800859 unsigned long val;
860 uint8_t idx;
861
862 if (sscanf(buf, "%lx", &val) != 1)
863 return -EINVAL;
864
Pratik Patel16aefdb2012-05-30 10:41:23 -0700865 mutex_lock(&drvdata->mutex);
866 idx = drvdata->addr_idx;
867 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
868 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
869 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800870 return -EPERM;
871 }
872
Pratik Patel16aefdb2012-05-30 10:41:23 -0700873 drvdata->addr_val[idx] = val;
874 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
875 drvdata->startstop_ctrl |= (1 << idx);
876 drvdata->enable_ctrl1 |= BIT(25);
877 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700878 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800879}
Pratik Patela9c0e062012-05-28 13:45:35 -0700880static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
881 etm_store_addr_start);
882
883static ssize_t etm_show_addr_stop(struct device *dev,
884 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800885{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700886 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800887 unsigned long val;
888 uint8_t idx;
889
Pratik Patel16aefdb2012-05-30 10:41:23 -0700890 mutex_lock(&drvdata->mutex);
891 idx = drvdata->addr_idx;
892 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
893 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
894 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800895 return -EPERM;
896 }
897
Pratik Patel16aefdb2012-05-30 10:41:23 -0700898 val = drvdata->addr_val[idx];
899 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800900 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
901}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800902
Pratik Patela9c0e062012-05-28 13:45:35 -0700903static ssize_t etm_store_addr_stop(struct device *dev,
904 struct device_attribute *attr,
905 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800906{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700907 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800908 unsigned long val;
909 uint8_t idx;
910
911 if (sscanf(buf, "%lx", &val) != 1)
912 return -EINVAL;
913
Pratik Patel16aefdb2012-05-30 10:41:23 -0700914 mutex_lock(&drvdata->mutex);
915 idx = drvdata->addr_idx;
916 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
917 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
918 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800919 return -EPERM;
920 }
921
Pratik Patel16aefdb2012-05-30 10:41:23 -0700922 drvdata->addr_val[idx] = val;
923 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
924 drvdata->startstop_ctrl |= (1 << (idx + 16));
925 drvdata->enable_ctrl1 |= BIT(25);
926 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700927 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800928}
Pratik Patela9c0e062012-05-28 13:45:35 -0700929static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
930 etm_store_addr_stop);
931
932static ssize_t etm_show_addr_acctype(struct device *dev,
933 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800934{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700935 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800936 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800937
Pratik Patel16aefdb2012-05-30 10:41:23 -0700938 mutex_lock(&drvdata->mutex);
939 val = drvdata->addr_acctype[drvdata->addr_idx];
940 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800941 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
942}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800943
Pratik Patela9c0e062012-05-28 13:45:35 -0700944static ssize_t etm_store_addr_acctype(struct device *dev,
945 struct device_attribute *attr,
946 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800947{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700948 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800949 unsigned long val;
950
951 if (sscanf(buf, "%lx", &val) != 1)
952 return -EINVAL;
953
Pratik Patel16aefdb2012-05-30 10:41:23 -0700954 mutex_lock(&drvdata->mutex);
955 drvdata->addr_acctype[drvdata->addr_idx] = val;
956 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700957 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800958}
Pratik Patela9c0e062012-05-28 13:45:35 -0700959static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
960 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800961
Pratik Patela9c0e062012-05-28 13:45:35 -0700962static ssize_t etm_show_cntr_idx(struct device *dev,
963 struct device_attribute *attr, char *buf)
964{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700965 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700966 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700967
Pratik Patel6630ebe2012-03-06 16:44:22 -0800968 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
969}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800970
Pratik Patela9c0e062012-05-28 13:45:35 -0700971static ssize_t etm_store_cntr_idx(struct device *dev,
972 struct device_attribute *attr,
973 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800974{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700975 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800976 unsigned long val;
977
978 if (sscanf(buf, "%lx", &val) != 1)
979 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700980 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800981 return -EINVAL;
982
983 /* Use mutex to ensure index doesn't change while it gets dereferenced
984 * multiple times within a mutex block elsewhere.
985 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700986 mutex_lock(&drvdata->mutex);
987 drvdata->cntr_idx = val;
988 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700989 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800990}
Pratik Patela9c0e062012-05-28 13:45:35 -0700991static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
992 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800993
Pratik Patela9c0e062012-05-28 13:45:35 -0700994static ssize_t etm_show_cntr_rld_val(struct device *dev,
995 struct device_attribute *attr, char *buf)
996{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700997 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700998 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700999
Pratik Patel16aefdb2012-05-30 10:41:23 -07001000 mutex_lock(&drvdata->mutex);
1001 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
1002 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001003 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1004}
1005
1006static ssize_t etm_store_cntr_rld_val(struct device *dev,
1007 struct device_attribute *attr,
1008 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001009{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001010 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001011 unsigned long val;
1012
1013 if (sscanf(buf, "%lx", &val) != 1)
1014 return -EINVAL;
1015
Pratik Patel16aefdb2012-05-30 10:41:23 -07001016 mutex_lock(&drvdata->mutex);
1017 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
1018 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001019 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001020}
Pratik Patela9c0e062012-05-28 13:45:35 -07001021static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
1022 etm_store_cntr_rld_val);
1023
1024static ssize_t etm_show_cntr_event(struct device *dev,
1025 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001026{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001027 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001028 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001029
Pratik Patel16aefdb2012-05-30 10:41:23 -07001030 mutex_lock(&drvdata->mutex);
1031 val = drvdata->cntr_event[drvdata->cntr_idx];
1032 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001033 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1034}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001035
Pratik Patela9c0e062012-05-28 13:45:35 -07001036static ssize_t etm_store_cntr_event(struct device *dev,
1037 struct device_attribute *attr,
1038 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001039{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001040 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001041 unsigned long val;
1042
1043 if (sscanf(buf, "%lx", &val) != 1)
1044 return -EINVAL;
1045
Pratik Patel16aefdb2012-05-30 10:41:23 -07001046 mutex_lock(&drvdata->mutex);
1047 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1048 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001049 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001050}
Pratik Patela9c0e062012-05-28 13:45:35 -07001051static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1052 etm_store_cntr_event);
1053
1054static ssize_t etm_show_cntr_rld_event(struct device *dev,
1055 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001056{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001057 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001058 unsigned long val;
1059
Pratik Patel16aefdb2012-05-30 10:41:23 -07001060 mutex_lock(&drvdata->mutex);
1061 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
1062 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001063 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1064}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001065
Pratik Patela9c0e062012-05-28 13:45:35 -07001066static ssize_t etm_store_cntr_rld_event(struct device *dev,
1067 struct device_attribute *attr,
1068 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001069{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001070 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001071 unsigned long val;
1072
1073 if (sscanf(buf, "%lx", &val) != 1)
1074 return -EINVAL;
1075
Pratik Patel16aefdb2012-05-30 10:41:23 -07001076 mutex_lock(&drvdata->mutex);
1077 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1078 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001079 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001080}
Pratik Patela9c0e062012-05-28 13:45:35 -07001081static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1082 etm_store_cntr_rld_event);
1083
1084static ssize_t etm_show_cntr_val(struct device *dev,
1085 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001086{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001087 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001088 unsigned long val;
1089
Pratik Patel16aefdb2012-05-30 10:41:23 -07001090 mutex_lock(&drvdata->mutex);
1091 val = drvdata->cntr_val[drvdata->cntr_idx];
1092 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001093 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1094}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001095
Pratik Patela9c0e062012-05-28 13:45:35 -07001096static ssize_t etm_store_cntr_val(struct device *dev,
1097 struct device_attribute *attr,
1098 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001099{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001100 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001101 unsigned long val;
1102
1103 if (sscanf(buf, "%lx", &val) != 1)
1104 return -EINVAL;
1105
Pratik Patel16aefdb2012-05-30 10:41:23 -07001106 mutex_lock(&drvdata->mutex);
1107 drvdata->cntr_val[drvdata->cntr_idx] = val;
1108 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001109 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001110}
Pratik Patela9c0e062012-05-28 13:45:35 -07001111static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1112 etm_store_cntr_val);
1113
1114static ssize_t etm_show_seq_12_event(struct device *dev,
1115 struct device_attribute *attr, char *buf)
1116{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001117 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001118 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001119
Pratik Patela9c0e062012-05-28 13:45:35 -07001120 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1121}
1122
1123static ssize_t etm_store_seq_12_event(struct device *dev,
1124 struct device_attribute *attr,
1125 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001126{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001127 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001128 unsigned long val;
1129
Pratik Patela9c0e062012-05-28 13:45:35 -07001130 if (sscanf(buf, "%lx", &val) != 1)
1131 return -EINVAL;
1132
Pratik Patel16aefdb2012-05-30 10:41:23 -07001133 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001134 return size;
1135}
1136static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1137 etm_store_seq_12_event);
1138
1139static ssize_t etm_show_seq_21_event(struct device *dev,
1140 struct device_attribute *attr, char *buf)
1141{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001142 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001143 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001144
Pratik Patel6630ebe2012-03-06 16:44:22 -08001145 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1146}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001147
Pratik Patela9c0e062012-05-28 13:45:35 -07001148static ssize_t etm_store_seq_21_event(struct device *dev,
1149 struct device_attribute *attr,
1150 const char *buf, size_t size)
1151{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001152 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001153 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001154
Pratik Patela9c0e062012-05-28 13:45:35 -07001155 if (sscanf(buf, "%lx", &val) != 1)
1156 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001157
Pratik Patel16aefdb2012-05-30 10:41:23 -07001158 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001159 return size;
1160}
1161static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1162 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001163
Pratik Patela9c0e062012-05-28 13:45:35 -07001164static ssize_t etm_show_seq_23_event(struct device *dev,
1165 struct device_attribute *attr, char *buf)
1166{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001167 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001168 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001169
Pratik Patela9c0e062012-05-28 13:45:35 -07001170 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1171}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001172
Pratik Patela9c0e062012-05-28 13:45:35 -07001173static ssize_t etm_store_seq_23_event(struct device *dev,
1174 struct device_attribute *attr,
1175 const char *buf, size_t size)
1176{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001177 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001178 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001179
Pratik Patela9c0e062012-05-28 13:45:35 -07001180 if (sscanf(buf, "%lx", &val) != 1)
1181 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001182
Pratik Patel16aefdb2012-05-30 10:41:23 -07001183 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001184 return size;
1185}
1186static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1187 etm_store_seq_23_event);
1188
1189static ssize_t etm_show_seq_31_event(struct device *dev,
1190 struct device_attribute *attr, char *buf)
1191{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001192 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001193 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001194
Pratik Patela9c0e062012-05-28 13:45:35 -07001195 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1196}
1197
1198static ssize_t etm_store_seq_31_event(struct device *dev,
1199 struct device_attribute *attr,
1200 const char *buf, size_t size)
1201{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001202 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001203 unsigned long val;
1204
1205 if (sscanf(buf, "%lx", &val) != 1)
1206 return -EINVAL;
1207
Pratik Patel16aefdb2012-05-30 10:41:23 -07001208 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001209 return size;
1210}
1211static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1212 etm_store_seq_31_event);
1213
1214static ssize_t etm_show_seq_32_event(struct device *dev,
1215 struct device_attribute *attr, char *buf)
1216{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001217 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001218 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001219
Pratik Patela9c0e062012-05-28 13:45:35 -07001220 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1221}
1222
1223static ssize_t etm_store_seq_32_event(struct device *dev,
1224 struct device_attribute *attr,
1225 const char *buf, size_t size)
1226{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001227 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001228 unsigned long val;
1229
1230 if (sscanf(buf, "%lx", &val) != 1)
1231 return -EINVAL;
1232
Pratik Patel16aefdb2012-05-30 10:41:23 -07001233 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001234 return size;
1235}
1236static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1237 etm_store_seq_32_event);
1238
1239static ssize_t etm_show_seq_13_event(struct device *dev,
1240 struct device_attribute *attr, char *buf)
1241{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001242 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001243 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001244
Pratik Patela9c0e062012-05-28 13:45:35 -07001245 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1246}
1247
1248static ssize_t etm_store_seq_13_event(struct device *dev,
1249 struct device_attribute *attr,
1250 const char *buf, size_t size)
1251{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001252 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001253 unsigned long val;
1254
1255 if (sscanf(buf, "%lx", &val) != 1)
1256 return -EINVAL;
1257
Pratik Patel16aefdb2012-05-30 10:41:23 -07001258 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001259 return size;
1260}
1261static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1262 etm_store_seq_13_event);
1263
1264static ssize_t etm_show_seq_curr_state(struct device *dev,
1265 struct device_attribute *attr, char *buf)
1266{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001267 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001268 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001269
Pratik Patela9c0e062012-05-28 13:45:35 -07001270 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1271}
1272
1273static ssize_t etm_store_seq_curr_state(struct device *dev,
1274 struct device_attribute *attr,
1275 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001276{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001277 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001278 unsigned long val;
1279
1280 if (sscanf(buf, "%lx", &val) != 1)
1281 return -EINVAL;
1282 if (val > ETM_SEQ_STATE_MAX_VAL)
1283 return -EINVAL;
1284
Pratik Patel16aefdb2012-05-30 10:41:23 -07001285 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001286 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001287}
Pratik Patela9c0e062012-05-28 13:45:35 -07001288static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1289 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001290
Pratik Patela9c0e062012-05-28 13:45:35 -07001291static ssize_t etm_show_ctxid_idx(struct device *dev,
1292 struct device_attribute *attr, char *buf)
1293{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001294 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001295 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001296
Pratik Patela9c0e062012-05-28 13:45:35 -07001297 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1298}
1299
1300static ssize_t etm_store_ctxid_idx(struct device *dev,
1301 struct device_attribute *attr,
1302 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001303{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001304 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001305 unsigned long val;
1306
1307 if (sscanf(buf, "%lx", &val) != 1)
1308 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001309 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001310 return -EINVAL;
1311
1312 /* Use mutex to ensure index doesn't change while it gets dereferenced
1313 * multiple times within a mutex block elsewhere.
1314 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001315 mutex_lock(&drvdata->mutex);
1316 drvdata->ctxid_idx = val;
1317 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001318 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001319}
Pratik Patela9c0e062012-05-28 13:45:35 -07001320static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1321 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001322
Pratik Patela9c0e062012-05-28 13:45:35 -07001323static ssize_t etm_show_ctxid_val(struct device *dev,
1324 struct device_attribute *attr, char *buf)
1325{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001326 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001327 unsigned long val;
1328
Pratik Patel16aefdb2012-05-30 10:41:23 -07001329 mutex_lock(&drvdata->mutex);
1330 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1331 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001332 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1333}
1334
1335static ssize_t etm_store_ctxid_val(struct device *dev,
1336 struct device_attribute *attr,
1337 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001338{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001339 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001340 unsigned long val;
1341
1342 if (sscanf(buf, "%lx", &val) != 1)
1343 return -EINVAL;
1344
Pratik Patel16aefdb2012-05-30 10:41:23 -07001345 mutex_lock(&drvdata->mutex);
1346 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1347 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001348 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001349}
Pratik Patela9c0e062012-05-28 13:45:35 -07001350static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1351 etm_store_ctxid_val);
1352
1353static ssize_t etm_show_ctxid_mask(struct device *dev,
1354 struct device_attribute *attr, char *buf)
1355{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001356 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001357 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001358
Pratik Patela9c0e062012-05-28 13:45:35 -07001359 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1360}
1361
1362static ssize_t etm_store_ctxid_mask(struct device *dev,
1363 struct device_attribute *attr,
1364 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001365{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001366 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001367 unsigned long val;
1368
Pratik Patela9c0e062012-05-28 13:45:35 -07001369 if (sscanf(buf, "%lx", &val) != 1)
1370 return -EINVAL;
1371
Pratik Patel16aefdb2012-05-30 10:41:23 -07001372 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001373 return size;
1374}
1375static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1376 etm_store_ctxid_mask);
1377
1378static ssize_t etm_show_sync_freq(struct device *dev,
1379 struct device_attribute *attr, char *buf)
1380{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001381 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001382 unsigned long val = drvdata->sync_freq;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001383 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1384}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001385
Pratik Patela9c0e062012-05-28 13:45:35 -07001386static ssize_t etm_store_sync_freq(struct device *dev,
1387 struct device_attribute *attr,
1388 const char *buf, size_t size)
1389{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001390 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001391 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001392
Pratik Patela9c0e062012-05-28 13:45:35 -07001393 if (sscanf(buf, "%lx", &val) != 1)
1394 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001395
Pratik Patel16aefdb2012-05-30 10:41:23 -07001396 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001397 return size;
1398}
1399static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1400 etm_store_sync_freq);
1401
1402static ssize_t etm_show_timestamp_event(struct device *dev,
1403 struct device_attribute *attr,
1404 char *buf)
1405{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001406 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001407 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001408
Pratik Patela9c0e062012-05-28 13:45:35 -07001409 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1410}
1411
1412static ssize_t etm_store_timestamp_event(struct device *dev,
1413 struct device_attribute *attr,
1414 const char *buf, size_t size)
1415{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001416 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001417 unsigned long val;
1418
1419 if (sscanf(buf, "%lx", &val) != 1)
1420 return -EINVAL;
1421
Pratik Patel16aefdb2012-05-30 10:41:23 -07001422 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001423 return size;
1424}
1425static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1426 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001427
1428static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001429 &dev_attr_nr_addr_cmp.attr,
1430 &dev_attr_nr_cntr.attr,
1431 &dev_attr_nr_ctxid_cmp.attr,
1432 &dev_attr_reset.attr,
1433 &dev_attr_mode.attr,
1434 &dev_attr_trigger_event.attr,
1435 &dev_attr_enable_event.attr,
1436 &dev_attr_fifofull_level.attr,
1437 &dev_attr_addr_idx.attr,
1438 &dev_attr_addr_single.attr,
1439 &dev_attr_addr_range.attr,
1440 &dev_attr_addr_start.attr,
1441 &dev_attr_addr_stop.attr,
1442 &dev_attr_addr_acctype.attr,
1443 &dev_attr_cntr_idx.attr,
1444 &dev_attr_cntr_rld_val.attr,
1445 &dev_attr_cntr_event.attr,
1446 &dev_attr_cntr_rld_event.attr,
1447 &dev_attr_cntr_val.attr,
1448 &dev_attr_seq_12_event.attr,
1449 &dev_attr_seq_21_event.attr,
1450 &dev_attr_seq_23_event.attr,
1451 &dev_attr_seq_31_event.attr,
1452 &dev_attr_seq_32_event.attr,
1453 &dev_attr_seq_13_event.attr,
1454 &dev_attr_seq_curr_state.attr,
1455 &dev_attr_ctxid_idx.attr,
1456 &dev_attr_ctxid_val.attr,
1457 &dev_attr_ctxid_mask.attr,
1458 &dev_attr_sync_freq.attr,
1459 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001460 NULL,
1461};
1462
1463static struct attribute_group etm_attr_grp = {
1464 .attrs = etm_attrs,
1465};
1466
Pratik Patel3b0ca882012-06-01 16:54:14 -07001467static const struct attribute_group *etm_attr_grps[] = {
1468 &etm_attr_grp,
1469 NULL,
1470};
1471
1472/* Memory mapped writes to clear os lock not supported */
1473static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001474{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001475 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001476
Pratik Patel3b0ca882012-06-01 16:54:14 -07001477 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1478 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001479}
1480
Stephen Boyda9510502012-04-24 16:23:34 -07001481static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001482{
Pratik Patel61de7302012-03-07 12:06:10 -08001483 switch (arch) {
1484 case PFT_ARCH_V1_1:
1485 break;
1486 default:
1487 return false;
1488 }
1489 return true;
1490}
1491
Pratik Patele6e41da2012-09-12 12:50:29 -07001492static void __devinit etm_prepare_arch(struct etm_drvdata *drvdata)
1493{
1494 /* Unlock OS lock first to allow memory mapped reads and writes. This
1495 * is required for Krait pass1
1496 * */
1497 etm_os_unlock(NULL);
1498 smp_call_function(etm_os_unlock, NULL, 1);
1499}
1500
1501static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001502{
Pratik Patel61de7302012-03-07 12:06:10 -08001503 uint32_t etmidr;
1504 uint32_t etmccr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001505 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001506
Pratik Patel3b0ca882012-06-01 16:54:14 -07001507 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001508 /* Vote for ETM power/clock enable */
Pratik Patelef6da292012-09-17 17:37:19 -07001509 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -07001510 /*
1511 * Clear power down bit since when this bit is set writes to
1512 * certain registers might be ignored.
1513 */
1514 etm_clr_pwrdwn(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001515 /* Set prog bit. It will be set from reset but this is included to
1516 * ensure it is set
1517 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001518 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001519
1520 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001521 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001522 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001523
Pratik Patel3b0ca882012-06-01 16:54:14 -07001524 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001525 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1526 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1527 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1528 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1529 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001530
Pratik Pateld1d65c92012-09-25 23:37:43 -07001531 etm_set_pwrdwn(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001532 /* Vote for ETM power/clock disable */
Pratik Patelef6da292012-09-17 17:37:19 -07001533 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001534 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001535}
1536
Pratik Patelc14b4df2012-09-05 18:07:59 -07001537static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1538{
1539 drvdata->arch = etm0drvdata->arch;
1540 drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
1541 drvdata->nr_cntr = etm0drvdata->nr_cntr;
1542 drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
1543 drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
1544 drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
1545}
1546
Pratik Patel3b0ca882012-06-01 16:54:14 -07001547static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001548{
1549 int i;
1550
1551 drvdata->trigger_event = 0x406F;
1552 drvdata->enable_event = 0x6F;
1553 drvdata->enable_ctrl1 = 0x1;
1554 drvdata->fifofull_level = 0x28;
1555 if (drvdata->nr_addr_cmp >= 2) {
1556 drvdata->addr_val[0] = (uint32_t) _stext;
1557 drvdata->addr_val[1] = (uint32_t) _etext;
1558 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1559 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1560 }
1561 for (i = 0; i < drvdata->nr_cntr; i++) {
1562 drvdata->cntr_event[i] = 0x406F;
1563 drvdata->cntr_rld_event[i] = 0x406F;
1564 }
1565 drvdata->seq_12_event = 0x406F;
1566 drvdata->seq_21_event = 0x406F;
1567 drvdata->seq_23_event = 0x406F;
1568 drvdata->seq_31_event = 0x406F;
1569 drvdata->seq_32_event = 0x406F;
1570 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001571 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1572 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1573 drvdata->sync_freq = 0x100;
1574 else
1575 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001576 drvdata->timestamp_event = 0x406F;
1577
1578 /* Overrides for Krait pass1 */
1579 if (cpu_is_krait_v1()) {
1580 /* Krait pass1 doesn't support include filtering and non-cycle
1581 * accurate tracing
1582 */
1583 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1584 drvdata->ctrl = 0x1000;
1585 drvdata->enable_ctrl1 = 0x1000000;
1586 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1587 drvdata->addr_val[i] = 0x0;
1588 drvdata->addr_acctype[i] = 0x0;
1589 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1590 }
1591 }
1592}
1593
Pratik Patel492b3012012-03-06 14:22:30 -08001594static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001595{
Pratik Patele5771792011-09-17 18:33:54 -07001596 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001597 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001598 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001599 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001600 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07001601 uint32_t reg_size;
1602 static int count;
1603 void *baddr;
1604 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001605 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001606
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001607 if (pdev->dev.of_node) {
1608 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1609 if (IS_ERR(pdata))
1610 return PTR_ERR(pdata);
1611 pdev->dev.platform_data = pdata;
1612 }
1613
Pratik Patel4a1b2522012-06-17 15:31:15 -07001614 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1615 if (!drvdata)
1616 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001617 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001618 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001619
Pratik Patel4a1b2522012-06-17 15:31:15 -07001620 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1621 if (!res)
1622 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07001623 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07001624
Pratik Patel4a1b2522012-06-17 15:31:15 -07001625 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1626 if (!drvdata->base)
1627 return -ENOMEM;
1628
Pratik Patel16aefdb2012-05-30 10:41:23 -07001629 mutex_init(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001630 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07001631
Pratik Patel4a1b2522012-06-17 15:31:15 -07001632 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001633 if (IS_ERR(drvdata->clk)) {
1634 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001635 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001636 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001637
Pratik Patel6fb38342012-06-03 14:51:38 -07001638 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001639 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001640 goto err0;
1641
Pratik Patel26477792012-09-07 01:35:36 -07001642 drvdata->cpu = count++;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001643
Pratik Patel16aefdb2012-05-30 10:41:23 -07001644 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001645 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001646 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001647
Pratik Patelc14b4df2012-09-05 18:07:59 -07001648 /* Use CPU0 to populate read-only configuration data for ETM0. For other
1649 * ETMs copy it over from ETM0.
1650 */
1651 if (drvdata->cpu == 0) {
Pratik Patele6e41da2012-09-12 12:50:29 -07001652 etm_prepare_arch(drvdata);
1653 smp_call_function_single(drvdata->cpu, etm_init_arch_data,
1654 drvdata, 1);
Pratik Patelc14b4df2012-09-05 18:07:59 -07001655 etm0drvdata = drvdata;
1656 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001657 etm_copy_arch_data(drvdata);
1658 }
1659 if (etm_arch_supported(drvdata->arch) == false) {
1660 ret = -EINVAL;
1661 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001662 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001663 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001664
Pratik Patel16aefdb2012-05-30 10:41:23 -07001665 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001666
Pratik Patel26477792012-09-07 01:35:36 -07001667 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
1668 if (baddr) {
1669 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
1670 dump.id = MSM_ETM0_REG + drvdata->cpu;
1671 dump.start_addr = virt_to_phys(baddr);
1672 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
1673 ret = msm_dump_table_register(&dump);
1674 if (ret) {
1675 devm_kfree(dev, baddr);
1676 dev_err(dev, "ETM REG dump setup failed\n");
1677 }
1678 } else {
1679 dev_err(dev, "ETM REG dump space allocation failed\n");
1680 }
1681
Pratik Patel4a1b2522012-06-17 15:31:15 -07001682 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001683 if (!desc) {
1684 ret = -ENOMEM;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001685 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001686 }
1687 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1688 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1689 desc->ops = &etm_cs_ops;
1690 desc->pdata = pdev->dev.platform_data;
1691 desc->dev = &pdev->dev;
1692 desc->groups = etm_attr_grps;
1693 desc->owner = THIS_MODULE;
1694 drvdata->csdev = coresight_register(desc);
1695 if (IS_ERR(drvdata->csdev)) {
1696 ret = PTR_ERR(drvdata->csdev);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001697 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001698 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001699
Pratik Patel4a1b2522012-06-17 15:31:15 -07001700 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001701
Pratik Patel3b0ca882012-06-01 16:54:14 -07001702 if (boot_enable)
1703 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001704
1705 return 0;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001706err1:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001707 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001708err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001709 wake_lock_destroy(&drvdata->wake_lock);
1710 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001711 return ret;
1712}
1713
Pratik Patelf6fe9182012-03-20 14:04:18 -07001714static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001715{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001716 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1717
1718 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001719 wake_lock_destroy(&drvdata->wake_lock);
1720 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001721 return 0;
1722}
1723
Pratik Patel9eae4822012-05-14 17:34:53 -07001724static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001725 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001726 {}
1727};
1728
Pratik Patel492b3012012-03-06 14:22:30 -08001729static struct platform_driver etm_driver = {
1730 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001731 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001732 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001733 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001734 .owner = THIS_MODULE,
1735 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001736 },
1737};
1738
Pratik Patel492b3012012-03-06 14:22:30 -08001739int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001740{
Pratik Patel492b3012012-03-06 14:22:30 -08001741 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001742}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001743module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001744
Pratik Patelf6fe9182012-03-20 14:04:18 -07001745void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001746{
Pratik Patel492b3012012-03-06 14:22:30 -08001747 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001748}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001749module_exit(etm_exit);
1750
1751MODULE_LICENSE("GPL v2");
1752MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");