blob: ce4d7d19115b0c7f011162d09518f8227870fcaa [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 Patel17f3b822011-11-21 12:41:47 -0800227/* ETM clock is derived from the processor clock and gets enabled on a
228 * logical OR of below items on Krait (pass2 onwards):
229 * 1.CPMR[ETMCLKEN] is 1
230 * 2.ETMCR[PD] is 0
231 * 3.ETMPDCR[PU] is 1
232 * 4.Reset is asserted (core or debug)
233 * 5.APB memory mapped requests (eg. EDAP access)
234 *
235 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
236 * enables
237 *
238 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
239 * clock vote in the driver and the save-restore code uses 1. above
240 * for its vote
241 */
Pratik Patelef6da292012-09-17 17:37:19 -0700242static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700243{
Pratik Patelef6da292012-09-17 17:37:19 -0700244 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700245
Pratik Patele6e41da2012-09-12 12:50:29 -0700246 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700247 etmpdcr |= BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700248 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
249 /* ensure pwrup completes before subsequent cp14 accesses */
250 mb();
251 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700252}
253
Pratik Patelef6da292012-09-17 17:37:19 -0700254static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700255{
Pratik Patelef6da292012-09-17 17:37:19 -0700256 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700257
Pratik Patele6e41da2012-09-12 12:50:29 -0700258 /* ensure pending cp14 accesses complete before clearing pwrup */
259 mb();
260 isb();
261 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700262 etmpdcr &= ~BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700263 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700264}
265
Pratik Patel3b0ca882012-06-01 16:54:14 -0700266static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700267{
268 uint32_t etmcr;
269 int count;
270
Pratik Patel3b0ca882012-06-01 16:54:14 -0700271 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700272 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700273 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700274 /* recommended by spec for cp14 accesses to ensure etmcr write is
275 * complete before polling etmsr
276 */
277 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700278 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700279 && count > 0; count--)
280 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800281 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700282 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700283}
284
Pratik Patel3b0ca882012-06-01 16:54:14 -0700285static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700286{
287 uint32_t etmcr;
288 int count;
289
Pratik Patel3b0ca882012-06-01 16:54:14 -0700290 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700291 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700292 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700293 /* recommended by spec for cp14 accesses to ensure etmcr write is
294 * complete before polling etmsr
295 */
296 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700297 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700298 && count > 0; count--)
299 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800300 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700301 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700302}
303
Pratik Patel66e1a412012-09-06 11:07:06 -0700304static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700305{
Pratik Patel17f3b822011-11-21 12:41:47 -0800306 int i;
Pratik Patel66e1a412012-09-06 11:07:06 -0700307 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700308
Pratik Patel3b0ca882012-06-01 16:54:14 -0700309 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800310 /* Vote for ETM power/clock enable */
Pratik Patelef6da292012-09-17 17:37:19 -0700311 etm_set_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700312 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700313
Pratik Patel3b0ca882012-06-01 16:54:14 -0700314 etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
315 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
316 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
317 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
318 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
319 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700320 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700321 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
322 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700323 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700324 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700325 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
326 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
327 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700328 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700329 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800330 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700331 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
332 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
333 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
334 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
335 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
336 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
337 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700338 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700339 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700340 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700341 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
342 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
343 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
344 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
345 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
346 etm_writel(drvdata, 0x00000000, ETMAUXCR);
347 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
348 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800349
Pratik Patel3b0ca882012-06-01 16:54:14 -0700350 etm_clr_prog(drvdata);
351 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700352
353 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700354}
355
Pratik Patel3b0ca882012-06-01 16:54:14 -0700356static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700357{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700358 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
359 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800360
Pratik Patel16aefdb2012-05-30 10:41:23 -0700361 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700362
Pratik Patel16aefdb2012-05-30 10:41:23 -0700363 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700364 if (ret)
365 goto err_clk;
366
Pratik Patel3b0ca882012-06-01 16:54:14 -0700367 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700368 /* executing __etm_enable on the cpu whose ETM is being enabled
369 * ensures that register writes occur when cpu is powered.
370 */
371 smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700372 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700373
Pratik Patel16aefdb2012-05-30 10:41:23 -0700374 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700375
Pratik Patel16aefdb2012-05-30 10:41:23 -0700376 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700377 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700378err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700379 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800380 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700381}
382
Pratik Patel66e1a412012-09-06 11:07:06 -0700383static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700384{
Pratik Patel66e1a412012-09-06 11:07:06 -0700385 struct etm_drvdata *drvdata = info;
386
Pratik Patel3b0ca882012-06-01 16:54:14 -0700387 ETM_UNLOCK(drvdata);
388 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700389
Pratik Patel17f3b822011-11-21 12:41:47 -0800390 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700391 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700392
Pratik Patel17f3b822011-11-21 12:41:47 -0800393 /* Vote for ETM power/clock disable */
Pratik Patelef6da292012-09-17 17:37:19 -0700394 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700395 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700396
397 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700398}
399
Pratik Patel3b0ca882012-06-01 16:54:14 -0700400static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700401{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700402 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800403
Pratik Patel16aefdb2012-05-30 10:41:23 -0700404 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700405
Pratik Patel3b0ca882012-06-01 16:54:14 -0700406 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700407 /* executing __etm_disable on the cpu whose ETM is being disabled
408 * ensures that register writes occur when cpu is powered.
409 */
410 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700411 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700412
Pratik Patel16aefdb2012-05-30 10:41:23 -0700413 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700414
Pratik Patel16aefdb2012-05-30 10:41:23 -0700415 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700416
Pratik Patel16aefdb2012-05-30 10:41:23 -0700417 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700418}
419
Pratik Patel3b0ca882012-06-01 16:54:14 -0700420static const struct coresight_ops_source etm_source_ops = {
421 .enable = etm_enable,
422 .disable = etm_disable,
423};
Pratik Patel17f3b822011-11-21 12:41:47 -0800424
Pratik Patel3b0ca882012-06-01 16:54:14 -0700425static const struct coresight_ops etm_cs_ops = {
426 .source_ops = &etm_source_ops,
427};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800428
Pratik Patela9c0e062012-05-28 13:45:35 -0700429static ssize_t etm_show_nr_addr_cmp(struct device *dev,
430 struct device_attribute *attr, char *buf)
431{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700432 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700433 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700434
Pratik Patela9c0e062012-05-28 13:45:35 -0700435 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
436}
437static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
438
439static ssize_t etm_show_nr_cntr(struct device *dev,
440 struct device_attribute *attr, char *buf)
441{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700442 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700443 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700444
Pratik Patela9c0e062012-05-28 13:45:35 -0700445 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
446}
447static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
448
449static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
450 struct device_attribute *attr, char *buf)
451{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700452 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700453 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700454
Pratik Patela9c0e062012-05-28 13:45:35 -0700455 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
456}
457static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
458
459static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
460 char *buf)
461{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700462 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700463 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700464
Pratik Patela9c0e062012-05-28 13:45:35 -0700465 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
466}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800467
Pratik Pateld30deda2012-02-01 14:40:55 -0800468/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700469static ssize_t etm_store_reset(struct device *dev,
470 struct device_attribute *attr, const char *buf,
471 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800472{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700473 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800474 int i;
475 unsigned long val;
476
477 if (sscanf(buf, "%lx", &val) != 1)
478 return -EINVAL;
479
Pratik Patel16aefdb2012-05-30 10:41:23 -0700480 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800481 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700482 drvdata->mode = ETM_MODE_EXCLUDE;
483 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800484 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700485 drvdata->mode |= ETM_MODE_CYCACC;
486 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800487 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700488 drvdata->trigger_event = 0x406F;
489 drvdata->startstop_ctrl = 0x0;
490 drvdata->enable_event = 0x6F;
491 drvdata->enable_ctrl1 = 0x1000000;
492 drvdata->fifofull_level = 0x28;
493 drvdata->addr_idx = 0x0;
494 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
495 drvdata->addr_val[i] = 0x0;
496 drvdata->addr_acctype[i] = 0x0;
497 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800498 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700499 drvdata->cntr_idx = 0x0;
500 for (i = 0; i < drvdata->nr_cntr; i++) {
501 drvdata->cntr_rld_val[i] = 0x0;
502 drvdata->cntr_event[i] = 0x406F;
503 drvdata->cntr_rld_event[i] = 0x406F;
504 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800505 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700506 drvdata->seq_12_event = 0x406F;
507 drvdata->seq_21_event = 0x406F;
508 drvdata->seq_23_event = 0x406F;
509 drvdata->seq_31_event = 0x406F;
510 drvdata->seq_32_event = 0x406F;
511 drvdata->seq_13_event = 0x406F;
512 drvdata->seq_curr_state = 0x0;
513 drvdata->ctxid_idx = 0x0;
514 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
515 drvdata->ctxid_val[i] = 0x0;
516 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700517 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
518 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
519 drvdata->sync_freq = 0x100;
520 else
521 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700522 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800523 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700524 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700525 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800526}
Pratik Patela9c0e062012-05-28 13:45:35 -0700527static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800528
Pratik Patela9c0e062012-05-28 13:45:35 -0700529static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
530 char *buf)
531{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700532 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700533 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700534
Pratik Patela9c0e062012-05-28 13:45:35 -0700535 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
536}
537
538static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
539 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800540{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700541 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800542 unsigned long val;
543
544 if (sscanf(buf, "%lx", &val) != 1)
545 return -EINVAL;
546
Pratik Patel16aefdb2012-05-30 10:41:23 -0700547 mutex_lock(&drvdata->mutex);
548 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800549
Pratik Patel16aefdb2012-05-30 10:41:23 -0700550 if (drvdata->mode & ETM_MODE_EXCLUDE)
551 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800552 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700553 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800554
Pratik Patel16aefdb2012-05-30 10:41:23 -0700555 if (drvdata->mode & ETM_MODE_CYCACC)
556 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800557 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700558 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800559
Pratik Patel16aefdb2012-05-30 10:41:23 -0700560 if (drvdata->mode & ETM_MODE_STALL)
561 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800562 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700563 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800564
Pratik Patel16aefdb2012-05-30 10:41:23 -0700565 if (drvdata->mode & ETM_MODE_TIMESTAMP)
566 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800567 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700568 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700569
Pratik Patel16aefdb2012-05-30 10:41:23 -0700570 if (drvdata->mode & ETM_MODE_CTXID)
571 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800572 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700573 drvdata->ctrl &= ~(BIT(14) | BIT(15));
574 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800575
Pratik Patela9c0e062012-05-28 13:45:35 -0700576 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800577}
Pratik Patela9c0e062012-05-28 13:45:35 -0700578static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800579
Pratik Patela9c0e062012-05-28 13:45:35 -0700580static ssize_t etm_show_trigger_event(struct device *dev,
581 struct device_attribute *attr, char *buf)
582{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700583 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700584 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700585
Pratik Patela9c0e062012-05-28 13:45:35 -0700586 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
587}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800588
Pratik Patela9c0e062012-05-28 13:45:35 -0700589static ssize_t etm_store_trigger_event(struct device *dev,
590 struct device_attribute *attr,
591 const char *buf, size_t size)
592{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700593 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700594 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800595
Pratik Patela9c0e062012-05-28 13:45:35 -0700596 if (sscanf(buf, "%lx", &val) != 1)
597 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800598
Pratik Patel16aefdb2012-05-30 10:41:23 -0700599 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700600 return size;
601}
602static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
603 etm_store_trigger_event);
604
605static ssize_t etm_show_enable_event(struct device *dev,
606 struct device_attribute *attr, char *buf)
607{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700608 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700609 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700610
Pratik Patela9c0e062012-05-28 13:45:35 -0700611 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
612}
613
614static ssize_t etm_store_enable_event(struct device *dev,
615 struct device_attribute *attr,
616 const char *buf, size_t size)
617{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700618 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700619 unsigned long val;
620
621 if (sscanf(buf, "%lx", &val) != 1)
622 return -EINVAL;
623
Pratik Patel16aefdb2012-05-30 10:41:23 -0700624 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700625 return size;
626}
627static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
628 etm_store_enable_event);
629
630static ssize_t etm_show_fifofull_level(struct device *dev,
631 struct device_attribute *attr, char *buf)
632{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700633 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700634 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700635
Pratik Patela9c0e062012-05-28 13:45:35 -0700636 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
637}
638
639static ssize_t etm_store_fifofull_level(struct device *dev,
640 struct device_attribute *attr,
641 const char *buf, size_t size)
642{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700643 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700644 unsigned long val;
645
646 if (sscanf(buf, "%lx", &val) != 1)
647 return -EINVAL;
648
Pratik Patel16aefdb2012-05-30 10:41:23 -0700649 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700650 return size;
651}
652static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
653 etm_store_fifofull_level);
654
655static ssize_t etm_show_addr_idx(struct device *dev,
656 struct device_attribute *attr, char *buf)
657{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700658 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700659 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700660
Pratik Patela9c0e062012-05-28 13:45:35 -0700661 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
662}
663
664static ssize_t etm_store_addr_idx(struct device *dev,
665 struct device_attribute *attr,
666 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800667{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700668 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800669 unsigned long val;
670
671 if (sscanf(buf, "%lx", &val) != 1)
672 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700673 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800674 return -EINVAL;
675
676 /* Use mutex to ensure index doesn't change while it gets dereferenced
677 * multiple times within a mutex block elsewhere.
678 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700679 mutex_lock(&drvdata->mutex);
680 drvdata->addr_idx = val;
681 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700682 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800683}
Pratik Patela9c0e062012-05-28 13:45:35 -0700684static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
685 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800686
Pratik Patela9c0e062012-05-28 13:45:35 -0700687static ssize_t etm_show_addr_single(struct device *dev,
688 struct device_attribute *attr, char *buf)
689{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700690 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700691 unsigned long val;
692 uint8_t idx;
693
Pratik Patel16aefdb2012-05-30 10:41:23 -0700694 mutex_lock(&drvdata->mutex);
695 idx = drvdata->addr_idx;
696 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
697 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
698 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700699 return -EPERM;
700 }
701
Pratik Patel16aefdb2012-05-30 10:41:23 -0700702 val = drvdata->addr_val[idx];
703 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700704 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
705}
706
707static ssize_t etm_store_addr_single(struct device *dev,
708 struct device_attribute *attr,
709 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800710{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700711 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800712 unsigned long val;
713 uint8_t idx;
714
715 if (sscanf(buf, "%lx", &val) != 1)
716 return -EINVAL;
717
Pratik Patel16aefdb2012-05-30 10:41:23 -0700718 mutex_lock(&drvdata->mutex);
719 idx = drvdata->addr_idx;
720 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
721 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
722 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800723 return -EPERM;
724 }
725
Pratik Patel16aefdb2012-05-30 10:41:23 -0700726 drvdata->addr_val[idx] = val;
727 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
728 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700729 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800730}
Pratik Patela9c0e062012-05-28 13:45:35 -0700731static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
732 etm_store_addr_single);
733
734static ssize_t etm_show_addr_range(struct device *dev,
735 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800736{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700737 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700738 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800739 uint8_t idx;
740
Pratik Patel16aefdb2012-05-30 10:41:23 -0700741 mutex_lock(&drvdata->mutex);
742 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700743 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700744 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700745 return -EPERM;
746 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700747 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
748 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
749 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
750 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
751 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800752 return -EPERM;
753 }
754
Pratik Patel16aefdb2012-05-30 10:41:23 -0700755 val1 = drvdata->addr_val[idx];
756 val2 = drvdata->addr_val[idx + 1];
757 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700758 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800759}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800760
Pratik Patela9c0e062012-05-28 13:45:35 -0700761static ssize_t etm_store_addr_range(struct device *dev,
762 struct device_attribute *attr,
763 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800764{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700765 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800766 unsigned long val1, val2;
767 uint8_t idx;
768
769 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
770 return -EINVAL;
771 /* lower address comparator cannot have a higher address value */
772 if (val1 > val2)
773 return -EINVAL;
774
Pratik Patel16aefdb2012-05-30 10:41:23 -0700775 mutex_lock(&drvdata->mutex);
776 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800777 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700778 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800779 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 drvdata->addr_val[idx] = val1;
790 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
791 drvdata->addr_val[idx + 1] = val2;
792 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
793 drvdata->enable_ctrl1 |= (1 << (idx/2));
794 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700795 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800796}
Pratik Patela9c0e062012-05-28 13:45:35 -0700797static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
798 etm_store_addr_range);
799
800static ssize_t etm_show_addr_start(struct device *dev,
801 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800802{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700803 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700804 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800805 uint8_t idx;
806
Pratik Patel16aefdb2012-05-30 10:41:23 -0700807 mutex_lock(&drvdata->mutex);
808 idx = drvdata->addr_idx;
809 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
810 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
811 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800812 return -EPERM;
813 }
814
Pratik Patel16aefdb2012-05-30 10:41:23 -0700815 val = drvdata->addr_val[idx];
816 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700817 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800818}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800819
Pratik Patela9c0e062012-05-28 13:45:35 -0700820static ssize_t etm_store_addr_start(struct device *dev,
821 struct device_attribute *attr,
822 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800823{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700824 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800825 unsigned long val;
826 uint8_t idx;
827
828 if (sscanf(buf, "%lx", &val) != 1)
829 return -EINVAL;
830
Pratik Patel16aefdb2012-05-30 10:41:23 -0700831 mutex_lock(&drvdata->mutex);
832 idx = drvdata->addr_idx;
833 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
834 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
835 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800836 return -EPERM;
837 }
838
Pratik Patel16aefdb2012-05-30 10:41:23 -0700839 drvdata->addr_val[idx] = val;
840 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
841 drvdata->startstop_ctrl |= (1 << idx);
842 drvdata->enable_ctrl1 |= BIT(25);
843 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700844 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800845}
Pratik Patela9c0e062012-05-28 13:45:35 -0700846static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
847 etm_store_addr_start);
848
849static ssize_t etm_show_addr_stop(struct device *dev,
850 struct device_attribute *attr, char *buf)
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 uint8_t idx;
855
Pratik Patel16aefdb2012-05-30 10:41:23 -0700856 mutex_lock(&drvdata->mutex);
857 idx = drvdata->addr_idx;
858 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
859 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
860 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800861 return -EPERM;
862 }
863
Pratik Patel16aefdb2012-05-30 10:41:23 -0700864 val = drvdata->addr_val[idx];
865 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800866 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
867}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800868
Pratik Patela9c0e062012-05-28 13:45:35 -0700869static ssize_t etm_store_addr_stop(struct device *dev,
870 struct device_attribute *attr,
871 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800872{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700873 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800874 unsigned long val;
875 uint8_t idx;
876
877 if (sscanf(buf, "%lx", &val) != 1)
878 return -EINVAL;
879
Pratik Patel16aefdb2012-05-30 10:41:23 -0700880 mutex_lock(&drvdata->mutex);
881 idx = drvdata->addr_idx;
882 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
883 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
884 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800885 return -EPERM;
886 }
887
Pratik Patel16aefdb2012-05-30 10:41:23 -0700888 drvdata->addr_val[idx] = val;
889 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
890 drvdata->startstop_ctrl |= (1 << (idx + 16));
891 drvdata->enable_ctrl1 |= BIT(25);
892 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700893 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800894}
Pratik Patela9c0e062012-05-28 13:45:35 -0700895static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
896 etm_store_addr_stop);
897
898static ssize_t etm_show_addr_acctype(struct device *dev,
899 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800900{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700901 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800902 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800903
Pratik Patel16aefdb2012-05-30 10:41:23 -0700904 mutex_lock(&drvdata->mutex);
905 val = drvdata->addr_acctype[drvdata->addr_idx];
906 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800907 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
908}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800909
Pratik Patela9c0e062012-05-28 13:45:35 -0700910static ssize_t etm_store_addr_acctype(struct device *dev,
911 struct device_attribute *attr,
912 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800913{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700914 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800915 unsigned long val;
916
917 if (sscanf(buf, "%lx", &val) != 1)
918 return -EINVAL;
919
Pratik Patel16aefdb2012-05-30 10:41:23 -0700920 mutex_lock(&drvdata->mutex);
921 drvdata->addr_acctype[drvdata->addr_idx] = val;
922 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700923 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800924}
Pratik Patela9c0e062012-05-28 13:45:35 -0700925static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
926 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800927
Pratik Patela9c0e062012-05-28 13:45:35 -0700928static ssize_t etm_show_cntr_idx(struct device *dev,
929 struct device_attribute *attr, char *buf)
930{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700931 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700932 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700933
Pratik Patel6630ebe2012-03-06 16:44:22 -0800934 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
935}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800936
Pratik Patela9c0e062012-05-28 13:45:35 -0700937static ssize_t etm_store_cntr_idx(struct device *dev,
938 struct device_attribute *attr,
939 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800940{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700941 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800942 unsigned long val;
943
944 if (sscanf(buf, "%lx", &val) != 1)
945 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700946 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800947 return -EINVAL;
948
949 /* Use mutex to ensure index doesn't change while it gets dereferenced
950 * multiple times within a mutex block elsewhere.
951 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700952 mutex_lock(&drvdata->mutex);
953 drvdata->cntr_idx = val;
954 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700955 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800956}
Pratik Patela9c0e062012-05-28 13:45:35 -0700957static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
958 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800959
Pratik Patela9c0e062012-05-28 13:45:35 -0700960static ssize_t etm_show_cntr_rld_val(struct device *dev,
961 struct device_attribute *attr, char *buf)
962{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700963 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700964 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700965
Pratik Patel16aefdb2012-05-30 10:41:23 -0700966 mutex_lock(&drvdata->mutex);
967 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
968 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700969 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
970}
971
972static ssize_t etm_store_cntr_rld_val(struct device *dev,
973 struct device_attribute *attr,
974 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800975{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700976 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800977 unsigned long val;
978
979 if (sscanf(buf, "%lx", &val) != 1)
980 return -EINVAL;
981
Pratik Patel16aefdb2012-05-30 10:41:23 -0700982 mutex_lock(&drvdata->mutex);
983 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
984 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700985 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800986}
Pratik Patela9c0e062012-05-28 13:45:35 -0700987static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
988 etm_store_cntr_rld_val);
989
990static ssize_t etm_show_cntr_event(struct device *dev,
991 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800992{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700993 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800994 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700995
Pratik Patel16aefdb2012-05-30 10:41:23 -0700996 mutex_lock(&drvdata->mutex);
997 val = drvdata->cntr_event[drvdata->cntr_idx];
998 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800999 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1000}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001001
Pratik Patela9c0e062012-05-28 13:45:35 -07001002static ssize_t etm_store_cntr_event(struct device *dev,
1003 struct device_attribute *attr,
1004 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001005{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001006 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001007 unsigned long val;
1008
1009 if (sscanf(buf, "%lx", &val) != 1)
1010 return -EINVAL;
1011
Pratik Patel16aefdb2012-05-30 10:41:23 -07001012 mutex_lock(&drvdata->mutex);
1013 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1014 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001015 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001016}
Pratik Patela9c0e062012-05-28 13:45:35 -07001017static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1018 etm_store_cntr_event);
1019
1020static ssize_t etm_show_cntr_rld_event(struct device *dev,
1021 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001022{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001023 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001024 unsigned long val;
1025
Pratik Patel16aefdb2012-05-30 10:41:23 -07001026 mutex_lock(&drvdata->mutex);
1027 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
1028 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001029 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1030}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001031
Pratik Patela9c0e062012-05-28 13:45:35 -07001032static ssize_t etm_store_cntr_rld_event(struct device *dev,
1033 struct device_attribute *attr,
1034 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001035{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001036 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001037 unsigned long val;
1038
1039 if (sscanf(buf, "%lx", &val) != 1)
1040 return -EINVAL;
1041
Pratik Patel16aefdb2012-05-30 10:41:23 -07001042 mutex_lock(&drvdata->mutex);
1043 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1044 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001045 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001046}
Pratik Patela9c0e062012-05-28 13:45:35 -07001047static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1048 etm_store_cntr_rld_event);
1049
1050static ssize_t etm_show_cntr_val(struct device *dev,
1051 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001052{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001053 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001054 unsigned long val;
1055
Pratik Patel16aefdb2012-05-30 10:41:23 -07001056 mutex_lock(&drvdata->mutex);
1057 val = drvdata->cntr_val[drvdata->cntr_idx];
1058 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001059 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1060}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001061
Pratik Patela9c0e062012-05-28 13:45:35 -07001062static ssize_t etm_store_cntr_val(struct device *dev,
1063 struct device_attribute *attr,
1064 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001065{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001066 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001067 unsigned long val;
1068
1069 if (sscanf(buf, "%lx", &val) != 1)
1070 return -EINVAL;
1071
Pratik Patel16aefdb2012-05-30 10:41:23 -07001072 mutex_lock(&drvdata->mutex);
1073 drvdata->cntr_val[drvdata->cntr_idx] = val;
1074 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001075 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001076}
Pratik Patela9c0e062012-05-28 13:45:35 -07001077static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1078 etm_store_cntr_val);
1079
1080static ssize_t etm_show_seq_12_event(struct device *dev,
1081 struct device_attribute *attr, char *buf)
1082{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001083 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001084 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001085
Pratik Patela9c0e062012-05-28 13:45:35 -07001086 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1087}
1088
1089static ssize_t etm_store_seq_12_event(struct device *dev,
1090 struct device_attribute *attr,
1091 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001092{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001093 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001094 unsigned long val;
1095
Pratik Patela9c0e062012-05-28 13:45:35 -07001096 if (sscanf(buf, "%lx", &val) != 1)
1097 return -EINVAL;
1098
Pratik Patel16aefdb2012-05-30 10:41:23 -07001099 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001100 return size;
1101}
1102static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1103 etm_store_seq_12_event);
1104
1105static ssize_t etm_show_seq_21_event(struct device *dev,
1106 struct device_attribute *attr, char *buf)
1107{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001108 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001109 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001110
Pratik Patel6630ebe2012-03-06 16:44:22 -08001111 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1112}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001113
Pratik Patela9c0e062012-05-28 13:45:35 -07001114static ssize_t etm_store_seq_21_event(struct device *dev,
1115 struct device_attribute *attr,
1116 const char *buf, size_t size)
1117{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001118 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001119 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001120
Pratik Patela9c0e062012-05-28 13:45:35 -07001121 if (sscanf(buf, "%lx", &val) != 1)
1122 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001123
Pratik Patel16aefdb2012-05-30 10:41:23 -07001124 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001125 return size;
1126}
1127static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1128 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001129
Pratik Patela9c0e062012-05-28 13:45:35 -07001130static ssize_t etm_show_seq_23_event(struct device *dev,
1131 struct device_attribute *attr, char *buf)
1132{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001133 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001134 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001135
Pratik Patela9c0e062012-05-28 13:45:35 -07001136 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1137}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001138
Pratik Patela9c0e062012-05-28 13:45:35 -07001139static ssize_t etm_store_seq_23_event(struct device *dev,
1140 struct device_attribute *attr,
1141 const char *buf, size_t size)
1142{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001143 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001144 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001145
Pratik Patela9c0e062012-05-28 13:45:35 -07001146 if (sscanf(buf, "%lx", &val) != 1)
1147 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001148
Pratik Patel16aefdb2012-05-30 10:41:23 -07001149 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001150 return size;
1151}
1152static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1153 etm_store_seq_23_event);
1154
1155static ssize_t etm_show_seq_31_event(struct device *dev,
1156 struct device_attribute *attr, char *buf)
1157{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001158 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001159 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001160
Pratik Patela9c0e062012-05-28 13:45:35 -07001161 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1162}
1163
1164static ssize_t etm_store_seq_31_event(struct device *dev,
1165 struct device_attribute *attr,
1166 const char *buf, size_t size)
1167{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001168 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001169 unsigned long val;
1170
1171 if (sscanf(buf, "%lx", &val) != 1)
1172 return -EINVAL;
1173
Pratik Patel16aefdb2012-05-30 10:41:23 -07001174 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001175 return size;
1176}
1177static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1178 etm_store_seq_31_event);
1179
1180static ssize_t etm_show_seq_32_event(struct device *dev,
1181 struct device_attribute *attr, char *buf)
1182{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001183 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001184 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001185
Pratik Patela9c0e062012-05-28 13:45:35 -07001186 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1187}
1188
1189static ssize_t etm_store_seq_32_event(struct device *dev,
1190 struct device_attribute *attr,
1191 const char *buf, size_t size)
1192{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001193 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001194 unsigned long val;
1195
1196 if (sscanf(buf, "%lx", &val) != 1)
1197 return -EINVAL;
1198
Pratik Patel16aefdb2012-05-30 10:41:23 -07001199 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001200 return size;
1201}
1202static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1203 etm_store_seq_32_event);
1204
1205static ssize_t etm_show_seq_13_event(struct device *dev,
1206 struct device_attribute *attr, char *buf)
1207{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001208 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001209 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001210
Pratik Patela9c0e062012-05-28 13:45:35 -07001211 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1212}
1213
1214static ssize_t etm_store_seq_13_event(struct device *dev,
1215 struct device_attribute *attr,
1216 const char *buf, size_t size)
1217{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001218 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001219 unsigned long val;
1220
1221 if (sscanf(buf, "%lx", &val) != 1)
1222 return -EINVAL;
1223
Pratik Patel16aefdb2012-05-30 10:41:23 -07001224 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001225 return size;
1226}
1227static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1228 etm_store_seq_13_event);
1229
1230static ssize_t etm_show_seq_curr_state(struct device *dev,
1231 struct device_attribute *attr, char *buf)
1232{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001233 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001234 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001235
Pratik Patela9c0e062012-05-28 13:45:35 -07001236 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1237}
1238
1239static ssize_t etm_store_seq_curr_state(struct device *dev,
1240 struct device_attribute *attr,
1241 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001242{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001243 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001244 unsigned long val;
1245
1246 if (sscanf(buf, "%lx", &val) != 1)
1247 return -EINVAL;
1248 if (val > ETM_SEQ_STATE_MAX_VAL)
1249 return -EINVAL;
1250
Pratik Patel16aefdb2012-05-30 10:41:23 -07001251 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001252 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001253}
Pratik Patela9c0e062012-05-28 13:45:35 -07001254static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1255 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001256
Pratik Patela9c0e062012-05-28 13:45:35 -07001257static ssize_t etm_show_ctxid_idx(struct device *dev,
1258 struct device_attribute *attr, char *buf)
1259{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001260 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001261 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001262
Pratik Patela9c0e062012-05-28 13:45:35 -07001263 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1264}
1265
1266static ssize_t etm_store_ctxid_idx(struct device *dev,
1267 struct device_attribute *attr,
1268 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001269{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001270 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001271 unsigned long val;
1272
1273 if (sscanf(buf, "%lx", &val) != 1)
1274 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001275 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001276 return -EINVAL;
1277
1278 /* Use mutex to ensure index doesn't change while it gets dereferenced
1279 * multiple times within a mutex block elsewhere.
1280 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001281 mutex_lock(&drvdata->mutex);
1282 drvdata->ctxid_idx = val;
1283 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001284 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001285}
Pratik Patela9c0e062012-05-28 13:45:35 -07001286static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1287 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001288
Pratik Patela9c0e062012-05-28 13:45:35 -07001289static ssize_t etm_show_ctxid_val(struct device *dev,
1290 struct device_attribute *attr, char *buf)
1291{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001292 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001293 unsigned long val;
1294
Pratik Patel16aefdb2012-05-30 10:41:23 -07001295 mutex_lock(&drvdata->mutex);
1296 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1297 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001298 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1299}
1300
1301static ssize_t etm_store_ctxid_val(struct device *dev,
1302 struct device_attribute *attr,
1303 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001304{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001305 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001306 unsigned long val;
1307
1308 if (sscanf(buf, "%lx", &val) != 1)
1309 return -EINVAL;
1310
Pratik Patel16aefdb2012-05-30 10:41:23 -07001311 mutex_lock(&drvdata->mutex);
1312 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1313 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001314 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001315}
Pratik Patela9c0e062012-05-28 13:45:35 -07001316static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1317 etm_store_ctxid_val);
1318
1319static ssize_t etm_show_ctxid_mask(struct device *dev,
1320 struct device_attribute *attr, char *buf)
1321{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001322 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001323 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001324
Pratik Patela9c0e062012-05-28 13:45:35 -07001325 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1326}
1327
1328static ssize_t etm_store_ctxid_mask(struct device *dev,
1329 struct device_attribute *attr,
1330 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001331{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001332 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001333 unsigned long val;
1334
Pratik Patela9c0e062012-05-28 13:45:35 -07001335 if (sscanf(buf, "%lx", &val) != 1)
1336 return -EINVAL;
1337
Pratik Patel16aefdb2012-05-30 10:41:23 -07001338 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001339 return size;
1340}
1341static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1342 etm_store_ctxid_mask);
1343
1344static ssize_t etm_show_sync_freq(struct device *dev,
1345 struct device_attribute *attr, char *buf)
1346{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001347 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001348 unsigned long val = drvdata->sync_freq;
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_sync_freq(struct device *dev,
1353 struct device_attribute *attr,
1354 const char *buf, size_t size)
1355{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001356 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001357 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001358
Pratik Patela9c0e062012-05-28 13:45:35 -07001359 if (sscanf(buf, "%lx", &val) != 1)
1360 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001361
Pratik Patel16aefdb2012-05-30 10:41:23 -07001362 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001363 return size;
1364}
1365static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1366 etm_store_sync_freq);
1367
1368static ssize_t etm_show_timestamp_event(struct device *dev,
1369 struct device_attribute *attr,
1370 char *buf)
1371{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001372 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001373 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001374
Pratik Patela9c0e062012-05-28 13:45:35 -07001375 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1376}
1377
1378static ssize_t etm_store_timestamp_event(struct device *dev,
1379 struct device_attribute *attr,
1380 const char *buf, size_t size)
1381{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001382 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001383 unsigned long val;
1384
1385 if (sscanf(buf, "%lx", &val) != 1)
1386 return -EINVAL;
1387
Pratik Patel16aefdb2012-05-30 10:41:23 -07001388 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001389 return size;
1390}
1391static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1392 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001393
1394static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001395 &dev_attr_nr_addr_cmp.attr,
1396 &dev_attr_nr_cntr.attr,
1397 &dev_attr_nr_ctxid_cmp.attr,
1398 &dev_attr_reset.attr,
1399 &dev_attr_mode.attr,
1400 &dev_attr_trigger_event.attr,
1401 &dev_attr_enable_event.attr,
1402 &dev_attr_fifofull_level.attr,
1403 &dev_attr_addr_idx.attr,
1404 &dev_attr_addr_single.attr,
1405 &dev_attr_addr_range.attr,
1406 &dev_attr_addr_start.attr,
1407 &dev_attr_addr_stop.attr,
1408 &dev_attr_addr_acctype.attr,
1409 &dev_attr_cntr_idx.attr,
1410 &dev_attr_cntr_rld_val.attr,
1411 &dev_attr_cntr_event.attr,
1412 &dev_attr_cntr_rld_event.attr,
1413 &dev_attr_cntr_val.attr,
1414 &dev_attr_seq_12_event.attr,
1415 &dev_attr_seq_21_event.attr,
1416 &dev_attr_seq_23_event.attr,
1417 &dev_attr_seq_31_event.attr,
1418 &dev_attr_seq_32_event.attr,
1419 &dev_attr_seq_13_event.attr,
1420 &dev_attr_seq_curr_state.attr,
1421 &dev_attr_ctxid_idx.attr,
1422 &dev_attr_ctxid_val.attr,
1423 &dev_attr_ctxid_mask.attr,
1424 &dev_attr_sync_freq.attr,
1425 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001426 NULL,
1427};
1428
1429static struct attribute_group etm_attr_grp = {
1430 .attrs = etm_attrs,
1431};
1432
Pratik Patel3b0ca882012-06-01 16:54:14 -07001433static const struct attribute_group *etm_attr_grps[] = {
1434 &etm_attr_grp,
1435 NULL,
1436};
1437
1438/* Memory mapped writes to clear os lock not supported */
1439static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001440{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001441 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001442
Pratik Patel3b0ca882012-06-01 16:54:14 -07001443 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1444 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001445}
1446
Stephen Boyda9510502012-04-24 16:23:34 -07001447static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001448{
Pratik Patel61de7302012-03-07 12:06:10 -08001449 switch (arch) {
1450 case PFT_ARCH_V1_1:
1451 break;
1452 default:
1453 return false;
1454 }
1455 return true;
1456}
1457
Pratik Patele6e41da2012-09-12 12:50:29 -07001458static void __devinit etm_prepare_arch(struct etm_drvdata *drvdata)
1459{
1460 /* Unlock OS lock first to allow memory mapped reads and writes. This
1461 * is required for Krait pass1
1462 * */
1463 etm_os_unlock(NULL);
1464 smp_call_function(etm_os_unlock, NULL, 1);
1465}
1466
1467static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001468{
Pratik Patel61de7302012-03-07 12:06:10 -08001469 uint32_t etmidr;
1470 uint32_t etmccr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001471 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001472
Pratik Patel3b0ca882012-06-01 16:54:14 -07001473 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001474 /* Vote for ETM power/clock enable */
Pratik Patelef6da292012-09-17 17:37:19 -07001475 etm_set_pwrup(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001476 /* Set prog bit. It will be set from reset but this is included to
1477 * ensure it is set
1478 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001479 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001480
1481 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001482 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001483 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001484
Pratik Patel3b0ca882012-06-01 16:54:14 -07001485 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001486 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1487 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1488 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1489 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1490 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001491
Pratik Patel17f3b822011-11-21 12:41:47 -08001492 /* Vote for ETM power/clock disable */
Pratik Patelef6da292012-09-17 17:37:19 -07001493 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001494 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001495}
1496
Pratik Patelc14b4df2012-09-05 18:07:59 -07001497static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1498{
1499 drvdata->arch = etm0drvdata->arch;
1500 drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
1501 drvdata->nr_cntr = etm0drvdata->nr_cntr;
1502 drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
1503 drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
1504 drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
1505}
1506
Pratik Patel3b0ca882012-06-01 16:54:14 -07001507static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001508{
1509 int i;
1510
1511 drvdata->trigger_event = 0x406F;
1512 drvdata->enable_event = 0x6F;
1513 drvdata->enable_ctrl1 = 0x1;
1514 drvdata->fifofull_level = 0x28;
1515 if (drvdata->nr_addr_cmp >= 2) {
1516 drvdata->addr_val[0] = (uint32_t) _stext;
1517 drvdata->addr_val[1] = (uint32_t) _etext;
1518 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1519 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1520 }
1521 for (i = 0; i < drvdata->nr_cntr; i++) {
1522 drvdata->cntr_event[i] = 0x406F;
1523 drvdata->cntr_rld_event[i] = 0x406F;
1524 }
1525 drvdata->seq_12_event = 0x406F;
1526 drvdata->seq_21_event = 0x406F;
1527 drvdata->seq_23_event = 0x406F;
1528 drvdata->seq_31_event = 0x406F;
1529 drvdata->seq_32_event = 0x406F;
1530 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001531 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1532 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1533 drvdata->sync_freq = 0x100;
1534 else
1535 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001536 drvdata->timestamp_event = 0x406F;
1537
1538 /* Overrides for Krait pass1 */
1539 if (cpu_is_krait_v1()) {
1540 /* Krait pass1 doesn't support include filtering and non-cycle
1541 * accurate tracing
1542 */
1543 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1544 drvdata->ctrl = 0x1000;
1545 drvdata->enable_ctrl1 = 0x1000000;
1546 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1547 drvdata->addr_val[i] = 0x0;
1548 drvdata->addr_acctype[i] = 0x0;
1549 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1550 }
1551 }
1552}
1553
Pratik Patel492b3012012-03-06 14:22:30 -08001554static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001555{
Pratik Patele5771792011-09-17 18:33:54 -07001556 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001557 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001558 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001559 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001560 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07001561 uint32_t reg_size;
1562 static int count;
1563 void *baddr;
1564 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001565 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001566
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001567 if (pdev->dev.of_node) {
1568 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1569 if (IS_ERR(pdata))
1570 return PTR_ERR(pdata);
1571 pdev->dev.platform_data = pdata;
1572 }
1573
Pratik Patel4a1b2522012-06-17 15:31:15 -07001574 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1575 if (!drvdata)
1576 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001577 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001578 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001579
Pratik Patel4a1b2522012-06-17 15:31:15 -07001580 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1581 if (!res)
1582 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07001583 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07001584
Pratik Patel4a1b2522012-06-17 15:31:15 -07001585 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1586 if (!drvdata->base)
1587 return -ENOMEM;
1588
Pratik Patel16aefdb2012-05-30 10:41:23 -07001589 mutex_init(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001590 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07001591
Pratik Patel4a1b2522012-06-17 15:31:15 -07001592 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001593 if (IS_ERR(drvdata->clk)) {
1594 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001595 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001596 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001597
Pratik Patel6fb38342012-06-03 14:51:38 -07001598 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001599 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001600 goto err0;
1601
Pratik Patel26477792012-09-07 01:35:36 -07001602 drvdata->cpu = count++;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001603
Pratik Patel16aefdb2012-05-30 10:41:23 -07001604 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001605 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001606 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001607
Pratik Patelc14b4df2012-09-05 18:07:59 -07001608 /* Use CPU0 to populate read-only configuration data for ETM0. For other
1609 * ETMs copy it over from ETM0.
1610 */
1611 if (drvdata->cpu == 0) {
Pratik Patele6e41da2012-09-12 12:50:29 -07001612 etm_prepare_arch(drvdata);
1613 smp_call_function_single(drvdata->cpu, etm_init_arch_data,
1614 drvdata, 1);
Pratik Patelc14b4df2012-09-05 18:07:59 -07001615 etm0drvdata = drvdata;
1616 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001617 etm_copy_arch_data(drvdata);
1618 }
1619 if (etm_arch_supported(drvdata->arch) == false) {
1620 ret = -EINVAL;
1621 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001622 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001623 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001624
Pratik Patel16aefdb2012-05-30 10:41:23 -07001625 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001626
Pratik Patel26477792012-09-07 01:35:36 -07001627 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
1628 if (baddr) {
1629 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
1630 dump.id = MSM_ETM0_REG + drvdata->cpu;
1631 dump.start_addr = virt_to_phys(baddr);
1632 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
1633 ret = msm_dump_table_register(&dump);
1634 if (ret) {
1635 devm_kfree(dev, baddr);
1636 dev_err(dev, "ETM REG dump setup failed\n");
1637 }
1638 } else {
1639 dev_err(dev, "ETM REG dump space allocation failed\n");
1640 }
1641
Pratik Patel4a1b2522012-06-17 15:31:15 -07001642 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001643 if (!desc) {
1644 ret = -ENOMEM;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001645 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001646 }
1647 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1648 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1649 desc->ops = &etm_cs_ops;
1650 desc->pdata = pdev->dev.platform_data;
1651 desc->dev = &pdev->dev;
1652 desc->groups = etm_attr_grps;
1653 desc->owner = THIS_MODULE;
1654 drvdata->csdev = coresight_register(desc);
1655 if (IS_ERR(drvdata->csdev)) {
1656 ret = PTR_ERR(drvdata->csdev);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001657 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001658 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001659
Pratik Patel4a1b2522012-06-17 15:31:15 -07001660 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001661
Pratik Patel3b0ca882012-06-01 16:54:14 -07001662 if (boot_enable)
1663 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001664
1665 return 0;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001666err1:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001667 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001668err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001669 wake_lock_destroy(&drvdata->wake_lock);
1670 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001671 return ret;
1672}
1673
Pratik Patelf6fe9182012-03-20 14:04:18 -07001674static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001675{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001676 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1677
1678 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001679 wake_lock_destroy(&drvdata->wake_lock);
1680 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001681 return 0;
1682}
1683
Pratik Patel9eae4822012-05-14 17:34:53 -07001684static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001685 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001686 {}
1687};
1688
Pratik Patel492b3012012-03-06 14:22:30 -08001689static struct platform_driver etm_driver = {
1690 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001691 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001692 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001693 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001694 .owner = THIS_MODULE,
1695 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001696 },
1697};
1698
Pratik Patel492b3012012-03-06 14:22:30 -08001699int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001700{
Pratik Patel492b3012012-03-06 14:22:30 -08001701 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001702}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001703module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001704
Pratik Patelf6fe9182012-03-20 14:04:18 -07001705void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001706{
Pratik Patel492b3012012-03-06 14:22:30 -08001707 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001708}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001709module_exit(etm_exit);
1710
1711MODULE_LICENSE("GPL v2");
1712MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");