blob: 2c0c2a0a0fdca5219fba9d4c312c3820666268b9 [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 Patel0a10be22012-10-23 21:12:07 -070028#include <linux/spinlock.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070029#include <linux/clk.h>
Pratik Patel9dbfa372012-10-23 22:36:40 -070030#include <linux/cpu.h>
Pratik Patel5f6d1af2012-06-13 15:48:13 -070031#include <linux/of_coresight.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070032#include <linux/coresight.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080033#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080034#include <mach/socinfo.h>
Pratik Patel26477792012-09-07 01:35:36 -070035#include <mach/msm_memory_dump.h>
Pratik Patel7831c082011-06-08 21:44:37 -070036
Pratik Patel1746b8f2012-06-02 21:11:41 -070037#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070038
Pratik Patele6e41da2012-09-12 12:50:29 -070039#define etm_writel_mm(drvdata, val, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070040 __raw_writel((val), drvdata->base + off)
Pratik Patele6e41da2012-09-12 12:50:29 -070041#define etm_readl_mm(drvdata, off) \
Pratik Patel3b0ca882012-06-01 16:54:14 -070042 __raw_readl(drvdata->base + off)
43
Pratik Patele6e41da2012-09-12 12:50:29 -070044#define etm_writel(drvdata, val, off) \
45({ \
46 if (cpu_is_krait_v3()) \
47 etm_writel_cp14(val, off); \
48 else \
49 etm_writel_mm(drvdata, val, off); \
50})
51#define etm_readl(drvdata, off) \
52({ \
53 uint32_t val; \
54 if (cpu_is_krait_v3()) \
55 val = etm_readl_cp14(off); \
56 else \
57 val = etm_readl_mm(drvdata, off); \
58 val; \
59})
60
Pratik Patel3b0ca882012-06-01 16:54:14 -070061#define ETM_LOCK(drvdata) \
62do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070063 /* recommended by spec to ensure ETM writes are committed prior
64 * to resuming execution
65 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070066 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070067 isb(); \
68 etm_writel_mm(drvdata, 0x0, CORESIGHT_LAR); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070069} while (0)
70#define ETM_UNLOCK(drvdata) \
71do { \
Pratik Patele6e41da2012-09-12 12:50:29 -070072 etm_writel_mm(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
73 /* ensure unlock and any pending writes are committed prior to
74 * programming ETM registers
75 */ \
Pratik Patel3b0ca882012-06-01 16:54:14 -070076 mb(); \
Pratik Patele6e41da2012-09-12 12:50:29 -070077 isb(); \
Pratik Patel3b0ca882012-06-01 16:54:14 -070078} while (0)
79
Pratik Patel7831c082011-06-08 21:44:37 -070080/*
81 * Device registers:
82 * 0x000 - 0x2FC: Trace registers
83 * 0x300 - 0x314: Management registers
84 * 0x318 - 0xEFC: Trace registers
85 *
86 * Coresight registers
87 * 0xF00 - 0xF9C: Management registers
88 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
89 * Trace registers in PFTv1.1
90 * 0xFA8 - 0xFFC: Management registers
91 */
92
93/* Trace registers (0x000-0x2FC) */
94#define ETMCR (0x000)
95#define ETMCCR (0x004)
96#define ETMTRIGGER (0x008)
97#define ETMSR (0x010)
98#define ETMSCR (0x014)
99#define ETMTSSCR (0x018)
100#define ETMTEEVR (0x020)
101#define ETMTECR1 (0x024)
102#define ETMFFLR (0x02C)
103#define ETMACVRn(n) (0x040 + (n * 4))
104#define ETMACTRn(n) (0x080 + (n * 4))
105#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
106#define ETMCNTENRn(n) (0x150 + (n * 4))
107#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
108#define ETMCNTVRn(n) (0x170 + (n * 4))
109#define ETMSQ12EVR (0x180)
110#define ETMSQ21EVR (0x184)
111#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800112#define ETMSQ31EVR (0x18C)
113#define ETMSQ32EVR (0x190)
114#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -0700115#define ETMSQR (0x19C)
116#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
117#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
118#define ETMCIDCMR (0x1BC)
119#define ETMIMPSPEC0 (0x1C0)
120#define ETMIMPSPEC1 (0x1C4)
121#define ETMIMPSPEC2 (0x1C8)
122#define ETMIMPSPEC3 (0x1CC)
123#define ETMIMPSPEC4 (0x1D0)
124#define ETMIMPSPEC5 (0x1D4)
125#define ETMIMPSPEC6 (0x1D8)
126#define ETMIMPSPEC7 (0x1DC)
127#define ETMSYNCFR (0x1E0)
128#define ETMIDR (0x1E4)
129#define ETMCCER (0x1E8)
130#define ETMEXTINSELR (0x1EC)
131#define ETMTESSEICR (0x1F0)
132#define ETMEIBCR (0x1F4)
133#define ETMTSEVR (0x1F8)
134#define ETMAUXCR (0x1FC)
135#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800136#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700137/* Management registers (0x300-0x314) */
138#define ETMOSLAR (0x300)
139#define ETMOSLSR (0x304)
140#define ETMOSSRR (0x308)
141#define ETMPDCR (0x310)
142#define ETMPDSR (0x314)
143
Pratik Patel61de7302012-03-07 12:06:10 -0800144#define ETM_MAX_ADDR_CMP (16)
145#define ETM_MAX_CNTR (4)
146#define ETM_MAX_CTXID_CMP (3)
147
Pratik Patel6630ebe2012-03-06 16:44:22 -0800148#define ETM_MODE_EXCLUDE BIT(0)
149#define ETM_MODE_CYCACC BIT(1)
150#define ETM_MODE_STALL BIT(2)
151#define ETM_MODE_TIMESTAMP BIT(3)
152#define ETM_MODE_CTXID BIT(4)
153#define ETM_MODE_ALL (0x1F)
154
155#define ETM_EVENT_MASK (0x1FFFF)
156#define ETM_SYNC_MASK (0xFFF)
157#define ETM_ALL_MASK (0xFFFFFFFF)
158
159#define ETM_SEQ_STATE_MAX_VAL (0x2)
160
Pratik Patel26477792012-09-07 01:35:36 -0700161#define ETM_REG_DUMP_VER_OFF (4)
162#define ETM_REG_DUMP_VER (1)
163
Pratik Patel3b0ca882012-06-01 16:54:14 -0700164enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800165 ETM_ADDR_TYPE_NONE,
166 ETM_ADDR_TYPE_SINGLE,
167 ETM_ADDR_TYPE_RANGE,
168 ETM_ADDR_TYPE_START,
169 ETM_ADDR_TYPE_STOP,
170};
171
Pratik Patel29cba152012-01-03 11:40:26 -0800172#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700173static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800174#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700175static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800176#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700177module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700178 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700179);
180
Pratik Patel938e1ff2012-09-28 23:21:46 -0700181#ifdef CONFIG_MSM_QDSS_ETM_PCSAVE_DEFAULT_ENABLE
182static int boot_pcsave_enable = 1;
183#else
184static int boot_pcsave_enable;
185#endif
186module_param_named(
187 boot_pcsave_enable, boot_pcsave_enable, int, S_IRUGO
188);
189
Pratik Patel16aefdb2012-05-30 10:41:23 -0700190struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700191 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700192 struct device *dev;
193 struct coresight_device *csdev;
194 struct clk *clk;
Pratik Patel0a10be22012-10-23 21:12:07 -0700195 spinlock_t spinlock;
Pratik Patel7831c082011-06-08 21:44:37 -0700196 struct wake_lock wake_lock;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700197 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800198 uint8_t arch;
Pratik Patelf3238df2012-10-19 16:19:12 -0700199 bool enable;
Pratik Patel61de7302012-03-07 12:06:10 -0800200 uint8_t nr_addr_cmp;
201 uint8_t nr_cntr;
202 uint8_t nr_ext_inp;
203 uint8_t nr_ext_out;
204 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800205 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800206 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800207 uint32_t ctrl;
208 uint32_t trigger_event;
209 uint32_t startstop_ctrl;
210 uint32_t enable_event;
211 uint32_t enable_ctrl1;
212 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800213 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800214 uint32_t addr_val[ETM_MAX_ADDR_CMP];
215 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800216 uint32_t addr_type[ETM_MAX_ADDR_CMP];
217 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800218 uint32_t cntr_rld_val[ETM_MAX_CNTR];
219 uint32_t cntr_event[ETM_MAX_CNTR];
220 uint32_t cntr_rld_event[ETM_MAX_CNTR];
221 uint32_t cntr_val[ETM_MAX_CNTR];
222 uint32_t seq_12_event;
223 uint32_t seq_21_event;
224 uint32_t seq_23_event;
225 uint32_t seq_31_event;
226 uint32_t seq_32_event;
227 uint32_t seq_13_event;
228 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800229 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800230 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
231 uint32_t ctxid_mask;
232 uint32_t sync_freq;
233 uint32_t timestamp_event;
Pratik Patel938e1ff2012-09-28 23:21:46 -0700234 bool pcsave_impl;
235 bool pcsave_enable;
Pratik Patel7831c082011-06-08 21:44:37 -0700236};
237
Pratik Patelc14b4df2012-09-05 18:07:59 -0700238static struct etm_drvdata *etm0drvdata;
239
Pratik Pateld1d65c92012-09-25 23:37:43 -0700240/*
241 * ETM clock is derived from the processor clock and gets enabled on a
242 * logical OR of below items on Krait (v2 onwards):
Pratik Patel17f3b822011-11-21 12:41:47 -0800243 * 1.CPMR[ETMCLKEN] is 1
244 * 2.ETMCR[PD] is 0
245 * 3.ETMPDCR[PU] is 1
246 * 4.Reset is asserted (core or debug)
247 * 5.APB memory mapped requests (eg. EDAP access)
248 *
249 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
250 * enables
251 *
Pratik Pateld1d65c92012-09-25 23:37:43 -0700252 * We rely on 5. to be able to access ETMCR/ETMPDCR and then use 2./3. above
253 * for ETM clock vote in the driver and the save-restore code uses 1. above
Pratik Patel17f3b822011-11-21 12:41:47 -0800254 * for its vote
255 */
Pratik Pateld1d65c92012-09-25 23:37:43 -0700256static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
257{
258 uint32_t etmcr;
259
260 /* ensure pending cp14 accesses complete before setting pwrdwn */
261 mb();
262 isb();
263 etmcr = etm_readl(drvdata, ETMCR);
264 etmcr |= BIT(0);
265 etm_writel(drvdata, etmcr, ETMCR);
266}
267
268static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
269{
270 uint32_t etmcr;
271
272 etmcr = etm_readl(drvdata, ETMCR);
273 etmcr &= ~BIT(0);
274 etm_writel(drvdata, etmcr, ETMCR);
275 /* ensure pwrup completes before subsequent cp14 accesses */
276 mb();
277 isb();
278}
279
Pratik Patelef6da292012-09-17 17:37:19 -0700280static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700281{
Pratik Patelef6da292012-09-17 17:37:19 -0700282 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700283
Pratik Patele6e41da2012-09-12 12:50:29 -0700284 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700285 etmpdcr |= BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700286 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
287 /* ensure pwrup completes before subsequent cp14 accesses */
288 mb();
289 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700290}
291
Pratik Patelef6da292012-09-17 17:37:19 -0700292static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700293{
Pratik Patelef6da292012-09-17 17:37:19 -0700294 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700295
Pratik Patele6e41da2012-09-12 12:50:29 -0700296 /* ensure pending cp14 accesses complete before clearing pwrup */
297 mb();
298 isb();
299 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700300 etmpdcr &= ~BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700301 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700302}
303
Pratik Patel3b0ca882012-06-01 16:54:14 -0700304static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700305{
306 uint32_t etmcr;
307 int count;
308
Pratik Patel3b0ca882012-06-01 16:54:14 -0700309 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700310 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700311 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700312 /* recommended by spec for cp14 accesses to ensure etmcr write is
313 * complete before polling etmsr
314 */
315 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700316 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700317 && count > 0; count--)
318 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800319 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700320 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700321}
322
Pratik Patel3b0ca882012-06-01 16:54:14 -0700323static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700324{
325 uint32_t etmcr;
326 int count;
327
Pratik Patel3b0ca882012-06-01 16:54:14 -0700328 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700329 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700330 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700331 /* recommended by spec for cp14 accesses to ensure etmcr write is
332 * complete before polling etmsr
333 */
334 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700335 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700336 && count > 0; count--)
337 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800338 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700339 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700340}
341
Pratik Patel938e1ff2012-09-28 23:21:46 -0700342static void etm_enable_pcsave(void *info)
343{
344 struct etm_drvdata *drvdata = info;
345
346 ETM_UNLOCK(drvdata);
347
Pratik Patel938e1ff2012-09-28 23:21:46 -0700348 /*
349 * ETMPDCR is only accessible via memory mapped interface and so use
350 * it first to enable power/clock to allow subsequent cp14 accesses.
351 */
352 etm_set_pwrup(drvdata);
353 etm_clr_pwrdwn(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700354
355 ETM_LOCK(drvdata);
356}
357
358static void etm_disable_pcsave(void *info)
359{
360 struct etm_drvdata *drvdata = info;
361
362 ETM_UNLOCK(drvdata);
363
Pratik Patelf3238df2012-10-19 16:19:12 -0700364 if (!drvdata->enable) {
365 etm_set_pwrdwn(drvdata);
366 etm_clr_pwrup(drvdata);
367 }
Pratik Patel938e1ff2012-09-28 23:21:46 -0700368
369 ETM_LOCK(drvdata);
370}
371
Pratik Patel66e1a412012-09-06 11:07:06 -0700372static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700373{
Pratik Patel17f3b822011-11-21 12:41:47 -0800374 int i;
Pratik Pateld1d65c92012-09-25 23:37:43 -0700375 uint32_t etmcr;
Pratik Patel66e1a412012-09-06 11:07:06 -0700376 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700377
Pratik Patel3b0ca882012-06-01 16:54:14 -0700378 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700379 /*
380 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
381 * memory mapped interface and so use it first to enable power/clock
382 * to allow subsequent cp14 accesses.
383 */
Pratik Patelef6da292012-09-17 17:37:19 -0700384 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -0700385 /*
386 * Clear power down bit since when this bit is set writes to
Pratik Patelf3238df2012-10-19 16:19:12 -0700387 * certain registers might be ignored. This is also a pre-requisite
388 * for trace enable.
Pratik Pateld1d65c92012-09-25 23:37:43 -0700389 */
390 etm_clr_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700391 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700392
Pratik Pateld1d65c92012-09-25 23:37:43 -0700393 etmcr = etm_readl(drvdata, ETMCR);
394 etmcr &= (BIT(10) | BIT(0));
395 etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700396 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
397 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
398 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
399 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
400 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700401 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700402 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
403 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700404 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700405 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700406 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
407 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
408 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700409 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700410 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800411 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700412 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
413 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
414 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
415 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
416 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
417 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
418 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700419 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700420 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700421 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700422 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
423 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
424 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
425 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
426 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
427 etm_writel(drvdata, 0x00000000, ETMAUXCR);
428 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
429 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800430
Pratik Patel3b0ca882012-06-01 16:54:14 -0700431 etm_clr_prog(drvdata);
432 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700433
434 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700435}
436
Pratik Patel3b0ca882012-06-01 16:54:14 -0700437static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700438{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700439 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
440 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800441
Pratik Patel16aefdb2012-05-30 10:41:23 -0700442 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700443
Pratik Patel16aefdb2012-05-30 10:41:23 -0700444 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700445 if (ret)
446 goto err_clk;
447
Pratik Patel0a10be22012-10-23 21:12:07 -0700448 spin_lock(&drvdata->spinlock);
449
Pratik Patelf3238df2012-10-19 16:19:12 -0700450 /*
451 * Executing __etm_enable on the cpu whose ETM is being enabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700452 * ensures that register writes occur when cpu is powered.
453 */
454 smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
Pratik Patelf3238df2012-10-19 16:19:12 -0700455 drvdata->enable = true;
Pratik Patel0a10be22012-10-23 21:12:07 -0700456
457 spin_unlock(&drvdata->spinlock);
Pratik Patel7831c082011-06-08 21:44:37 -0700458
Pratik Patel16aefdb2012-05-30 10:41:23 -0700459 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700460
Pratik Patel16aefdb2012-05-30 10:41:23 -0700461 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700462 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700463err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700464 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800465 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700466}
467
Pratik Patel66e1a412012-09-06 11:07:06 -0700468static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700469{
Pratik Patel66e1a412012-09-06 11:07:06 -0700470 struct etm_drvdata *drvdata = info;
471
Pratik Patel3b0ca882012-06-01 16:54:14 -0700472 ETM_UNLOCK(drvdata);
473 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700474
Pratik Patel17f3b822011-11-21 12:41:47 -0800475 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700476 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700477
Pratik Patelf3238df2012-10-19 16:19:12 -0700478 if (!drvdata->pcsave_enable) {
479 etm_set_pwrdwn(drvdata);
480 etm_clr_pwrup(drvdata);
481 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700482 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700483
484 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700485}
486
Pratik Patel3b0ca882012-06-01 16:54:14 -0700487static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700488{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700489 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800490
Pratik Patel16aefdb2012-05-30 10:41:23 -0700491 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700492
Pratik Patel0a10be22012-10-23 21:12:07 -0700493 spin_lock(&drvdata->spinlock);
494
Pratik Patelf3238df2012-10-19 16:19:12 -0700495 /*
496 * Executing __etm_disable on the cpu whose ETM is being disabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700497 * ensures that register writes occur when cpu is powered.
498 */
499 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patelf3238df2012-10-19 16:19:12 -0700500 drvdata->enable = false;
Pratik Patel0a10be22012-10-23 21:12:07 -0700501
502 spin_unlock(&drvdata->spinlock);
Pratik Patel7831c082011-06-08 21:44:37 -0700503
Pratik Patel16aefdb2012-05-30 10:41:23 -0700504 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700505
Pratik Patel16aefdb2012-05-30 10:41:23 -0700506 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700507
Pratik Patel16aefdb2012-05-30 10:41:23 -0700508 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700509}
510
Pratik Patel3b0ca882012-06-01 16:54:14 -0700511static const struct coresight_ops_source etm_source_ops = {
512 .enable = etm_enable,
513 .disable = etm_disable,
514};
Pratik Patel17f3b822011-11-21 12:41:47 -0800515
Pratik Patel3b0ca882012-06-01 16:54:14 -0700516static const struct coresight_ops etm_cs_ops = {
517 .source_ops = &etm_source_ops,
518};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800519
Pratik Patela9c0e062012-05-28 13:45:35 -0700520static ssize_t etm_show_nr_addr_cmp(struct device *dev,
521 struct device_attribute *attr, char *buf)
522{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700523 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700524 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700525
Pratik Patela9c0e062012-05-28 13:45:35 -0700526 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
527}
528static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
529
530static ssize_t etm_show_nr_cntr(struct device *dev,
531 struct device_attribute *attr, char *buf)
532{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700533 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700534 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700535
Pratik Patela9c0e062012-05-28 13:45:35 -0700536 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
537}
538static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
539
540static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
541 struct device_attribute *attr, char *buf)
542{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700543 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700544 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700545
Pratik Patela9c0e062012-05-28 13:45:35 -0700546 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
547}
548static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
549
550static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
551 char *buf)
552{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700553 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700554 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700555
Pratik Patela9c0e062012-05-28 13:45:35 -0700556 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
557}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800558
Pratik Pateld30deda2012-02-01 14:40:55 -0800559/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700560static ssize_t etm_store_reset(struct device *dev,
561 struct device_attribute *attr, const char *buf,
562 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800563{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700564 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800565 int i;
566 unsigned long val;
567
568 if (sscanf(buf, "%lx", &val) != 1)
569 return -EINVAL;
570
Pratik Patel0a10be22012-10-23 21:12:07 -0700571 spin_lock(&drvdata->spinlock);
Pratik Pateld30deda2012-02-01 14:40:55 -0800572 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700573 drvdata->mode = ETM_MODE_EXCLUDE;
574 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800575 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700576 drvdata->mode |= ETM_MODE_CYCACC;
577 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800578 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700579 drvdata->trigger_event = 0x406F;
580 drvdata->startstop_ctrl = 0x0;
581 drvdata->enable_event = 0x6F;
582 drvdata->enable_ctrl1 = 0x1000000;
583 drvdata->fifofull_level = 0x28;
584 drvdata->addr_idx = 0x0;
585 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
586 drvdata->addr_val[i] = 0x0;
587 drvdata->addr_acctype[i] = 0x0;
588 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800589 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700590 drvdata->cntr_idx = 0x0;
591 for (i = 0; i < drvdata->nr_cntr; i++) {
592 drvdata->cntr_rld_val[i] = 0x0;
593 drvdata->cntr_event[i] = 0x406F;
594 drvdata->cntr_rld_event[i] = 0x406F;
595 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800596 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700597 drvdata->seq_12_event = 0x406F;
598 drvdata->seq_21_event = 0x406F;
599 drvdata->seq_23_event = 0x406F;
600 drvdata->seq_31_event = 0x406F;
601 drvdata->seq_32_event = 0x406F;
602 drvdata->seq_13_event = 0x406F;
603 drvdata->seq_curr_state = 0x0;
604 drvdata->ctxid_idx = 0x0;
605 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
606 drvdata->ctxid_val[i] = 0x0;
607 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700608 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
609 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
610 drvdata->sync_freq = 0x100;
611 else
612 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700613 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800614 }
Pratik Patel0a10be22012-10-23 21:12:07 -0700615 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700616 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800617}
Pratik Patela9c0e062012-05-28 13:45:35 -0700618static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800619
Pratik Patela9c0e062012-05-28 13:45:35 -0700620static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
621 char *buf)
622{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700623 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700624 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700625
Pratik Patela9c0e062012-05-28 13:45:35 -0700626 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
627}
628
629static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
630 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800631{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700632 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800633 unsigned long val;
634
635 if (sscanf(buf, "%lx", &val) != 1)
636 return -EINVAL;
637
Pratik Patel0a10be22012-10-23 21:12:07 -0700638 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700639 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800640
Pratik Patel16aefdb2012-05-30 10:41:23 -0700641 if (drvdata->mode & ETM_MODE_EXCLUDE)
642 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800643 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700644 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800645
Pratik Patel16aefdb2012-05-30 10:41:23 -0700646 if (drvdata->mode & ETM_MODE_CYCACC)
647 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800648 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700649 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800650
Pratik Patel16aefdb2012-05-30 10:41:23 -0700651 if (drvdata->mode & ETM_MODE_STALL)
652 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800653 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700654 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800655
Pratik Patel16aefdb2012-05-30 10:41:23 -0700656 if (drvdata->mode & ETM_MODE_TIMESTAMP)
657 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800658 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700659 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700660
Pratik Patel16aefdb2012-05-30 10:41:23 -0700661 if (drvdata->mode & ETM_MODE_CTXID)
662 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800663 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700664 drvdata->ctrl &= ~(BIT(14) | BIT(15));
Pratik Patel0a10be22012-10-23 21:12:07 -0700665 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800666
Pratik Patela9c0e062012-05-28 13:45:35 -0700667 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800668}
Pratik Patela9c0e062012-05-28 13:45:35 -0700669static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800670
Pratik Patela9c0e062012-05-28 13:45:35 -0700671static ssize_t etm_show_trigger_event(struct device *dev,
672 struct device_attribute *attr, char *buf)
673{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700674 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700675 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700676
Pratik Patela9c0e062012-05-28 13:45:35 -0700677 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
678}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800679
Pratik Patela9c0e062012-05-28 13:45:35 -0700680static ssize_t etm_store_trigger_event(struct device *dev,
681 struct device_attribute *attr,
682 const char *buf, size_t size)
683{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700684 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700685 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800686
Pratik Patela9c0e062012-05-28 13:45:35 -0700687 if (sscanf(buf, "%lx", &val) != 1)
688 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800689
Pratik Patel16aefdb2012-05-30 10:41:23 -0700690 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700691 return size;
692}
693static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
694 etm_store_trigger_event);
695
696static ssize_t etm_show_enable_event(struct device *dev,
697 struct device_attribute *attr, char *buf)
698{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700699 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700700 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700701
Pratik Patela9c0e062012-05-28 13:45:35 -0700702 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
703}
704
705static ssize_t etm_store_enable_event(struct device *dev,
706 struct device_attribute *attr,
707 const char *buf, size_t size)
708{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700709 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700710 unsigned long val;
711
712 if (sscanf(buf, "%lx", &val) != 1)
713 return -EINVAL;
714
Pratik Patel16aefdb2012-05-30 10:41:23 -0700715 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700716 return size;
717}
718static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
719 etm_store_enable_event);
720
721static ssize_t etm_show_fifofull_level(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 Patel16aefdb2012-05-30 10:41:23 -0700725 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700726
Pratik Patela9c0e062012-05-28 13:45:35 -0700727 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
728}
729
730static ssize_t etm_store_fifofull_level(struct device *dev,
731 struct device_attribute *attr,
732 const char *buf, size_t size)
733{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700734 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700735 unsigned long val;
736
737 if (sscanf(buf, "%lx", &val) != 1)
738 return -EINVAL;
739
Pratik Patel16aefdb2012-05-30 10:41:23 -0700740 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700741 return size;
742}
743static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
744 etm_store_fifofull_level);
745
746static ssize_t etm_show_addr_idx(struct device *dev,
747 struct device_attribute *attr, char *buf)
748{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700749 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700750 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700751
Pratik Patela9c0e062012-05-28 13:45:35 -0700752 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
753}
754
755static ssize_t etm_store_addr_idx(struct device *dev,
756 struct device_attribute *attr,
757 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800758{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700759 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800760 unsigned long val;
761
762 if (sscanf(buf, "%lx", &val) != 1)
763 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700764 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800765 return -EINVAL;
766
Pratik Patel0a10be22012-10-23 21:12:07 -0700767 /*
768 * Use spinlock to ensure index doesn't change while it gets
769 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -0800770 */
Pratik Patel0a10be22012-10-23 21:12:07 -0700771 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700772 drvdata->addr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -0700773 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700774 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800775}
Pratik Patela9c0e062012-05-28 13:45:35 -0700776static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
777 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800778
Pratik Patela9c0e062012-05-28 13:45:35 -0700779static ssize_t etm_show_addr_single(struct device *dev,
780 struct device_attribute *attr, char *buf)
781{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700782 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700783 unsigned long val;
784 uint8_t idx;
785
Pratik Patel0a10be22012-10-23 21:12:07 -0700786 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700787 idx = drvdata->addr_idx;
788 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
789 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700790 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700791 return -EPERM;
792 }
793
Pratik Patel16aefdb2012-05-30 10:41:23 -0700794 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700795 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700796 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
797}
798
799static ssize_t etm_store_addr_single(struct device *dev,
800 struct device_attribute *attr,
801 const char *buf, size_t size)
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 Patel6630ebe2012-03-06 16:44:22 -0800804 unsigned long val;
805 uint8_t idx;
806
807 if (sscanf(buf, "%lx", &val) != 1)
808 return -EINVAL;
809
Pratik Patel0a10be22012-10-23 21:12:07 -0700810 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700811 idx = drvdata->addr_idx;
812 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
813 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700814 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800815 return -EPERM;
816 }
817
Pratik Patel16aefdb2012-05-30 10:41:23 -0700818 drvdata->addr_val[idx] = val;
819 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
Pratik Patel0a10be22012-10-23 21:12:07 -0700820 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700821 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800822}
Pratik Patela9c0e062012-05-28 13:45:35 -0700823static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
824 etm_store_addr_single);
825
826static ssize_t etm_show_addr_range(struct device *dev,
827 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800828{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700829 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700830 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800831 uint8_t idx;
832
Pratik Patel0a10be22012-10-23 21:12:07 -0700833 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700834 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700835 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700836 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700837 return -EPERM;
838 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700839 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
840 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
841 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
842 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700843 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800844 return -EPERM;
845 }
846
Pratik Patel16aefdb2012-05-30 10:41:23 -0700847 val1 = drvdata->addr_val[idx];
848 val2 = drvdata->addr_val[idx + 1];
Pratik Patel0a10be22012-10-23 21:12:07 -0700849 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700850 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800851}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800852
Pratik Patela9c0e062012-05-28 13:45:35 -0700853static ssize_t etm_store_addr_range(struct device *dev,
854 struct device_attribute *attr,
855 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800856{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700857 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800858 unsigned long val1, val2;
859 uint8_t idx;
860
861 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
862 return -EINVAL;
863 /* lower address comparator cannot have a higher address value */
864 if (val1 > val2)
865 return -EINVAL;
866
Pratik Patel0a10be22012-10-23 21:12:07 -0700867 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700868 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800869 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700870 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800871 return -EPERM;
872 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700873 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
874 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
875 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
876 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700877 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800878 return -EPERM;
879 }
880
Pratik Patel16aefdb2012-05-30 10:41:23 -0700881 drvdata->addr_val[idx] = val1;
882 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
883 drvdata->addr_val[idx + 1] = val2;
884 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
885 drvdata->enable_ctrl1 |= (1 << (idx/2));
Pratik Patel0a10be22012-10-23 21:12:07 -0700886 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700887 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800888}
Pratik Patela9c0e062012-05-28 13:45:35 -0700889static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
890 etm_store_addr_range);
891
892static ssize_t etm_show_addr_start(struct device *dev,
893 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800894{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700895 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700896 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800897 uint8_t idx;
898
Pratik Patel0a10be22012-10-23 21:12:07 -0700899 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700900 idx = drvdata->addr_idx;
901 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
902 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700903 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800904 return -EPERM;
905 }
906
Pratik Patel16aefdb2012-05-30 10:41:23 -0700907 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700908 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700909 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800910}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800911
Pratik Patela9c0e062012-05-28 13:45:35 -0700912static ssize_t etm_store_addr_start(struct device *dev,
913 struct device_attribute *attr,
914 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800915{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700916 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800917 unsigned long val;
918 uint8_t idx;
919
920 if (sscanf(buf, "%lx", &val) != 1)
921 return -EINVAL;
922
Pratik Patel0a10be22012-10-23 21:12:07 -0700923 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700924 idx = drvdata->addr_idx;
925 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
926 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700927 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800928 return -EPERM;
929 }
930
Pratik Patel16aefdb2012-05-30 10:41:23 -0700931 drvdata->addr_val[idx] = val;
932 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
933 drvdata->startstop_ctrl |= (1 << idx);
934 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -0700935 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700936 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800937}
Pratik Patela9c0e062012-05-28 13:45:35 -0700938static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
939 etm_store_addr_start);
940
941static ssize_t etm_show_addr_stop(struct device *dev,
942 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800943{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700944 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800945 unsigned long val;
946 uint8_t idx;
947
Pratik Patel0a10be22012-10-23 21:12:07 -0700948 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700949 idx = drvdata->addr_idx;
950 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
951 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700952 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800953 return -EPERM;
954 }
955
Pratik Patel16aefdb2012-05-30 10:41:23 -0700956 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700957 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800958 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
959}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800960
Pratik Patela9c0e062012-05-28 13:45:35 -0700961static ssize_t etm_store_addr_stop(struct device *dev,
962 struct device_attribute *attr,
963 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800964{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700965 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800966 unsigned long val;
967 uint8_t idx;
968
969 if (sscanf(buf, "%lx", &val) != 1)
970 return -EINVAL;
971
Pratik Patel0a10be22012-10-23 21:12:07 -0700972 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700973 idx = drvdata->addr_idx;
974 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
975 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700976 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800977 return -EPERM;
978 }
979
Pratik Patel16aefdb2012-05-30 10:41:23 -0700980 drvdata->addr_val[idx] = val;
981 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
982 drvdata->startstop_ctrl |= (1 << (idx + 16));
983 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -0700984 spin_unlock(&drvdata->spinlock);
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(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
988 etm_store_addr_stop);
989
990static ssize_t etm_show_addr_acctype(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 Patel6630ebe2012-03-06 16:44:22 -0800995
Pratik Patel0a10be22012-10-23 21:12:07 -0700996 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700997 val = drvdata->addr_acctype[drvdata->addr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700998 spin_unlock(&drvdata->spinlock);
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_addr_acctype(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 Patel0a10be22012-10-23 21:12:07 -07001012 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001013 drvdata->addr_acctype[drvdata->addr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001014 spin_unlock(&drvdata->spinlock);
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(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
1018 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001019
Pratik Patela9c0e062012-05-28 13:45:35 -07001020static ssize_t etm_show_cntr_idx(struct device *dev,
1021 struct device_attribute *attr, char *buf)
1022{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001023 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001024 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001025
Pratik Patel6630ebe2012-03-06 16:44:22 -08001026 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1027}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001028
Pratik Patela9c0e062012-05-28 13:45:35 -07001029static ssize_t etm_store_cntr_idx(struct device *dev,
1030 struct device_attribute *attr,
1031 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001032{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001033 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001034 unsigned long val;
1035
1036 if (sscanf(buf, "%lx", &val) != 1)
1037 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001038 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001039 return -EINVAL;
1040
Pratik Patel0a10be22012-10-23 21:12:07 -07001041 /*
1042 * Use spinlock to ensure index doesn't change while it gets
1043 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001044 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001045 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001046 drvdata->cntr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001047 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001048 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001049}
Pratik Patela9c0e062012-05-28 13:45:35 -07001050static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
1051 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001052
Pratik Patela9c0e062012-05-28 13:45:35 -07001053static ssize_t etm_show_cntr_rld_val(struct device *dev,
1054 struct device_attribute *attr, char *buf)
1055{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001056 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001057 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001058
Pratik Patel0a10be22012-10-23 21:12:07 -07001059 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001060 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001061 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001062 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1063}
1064
1065static ssize_t etm_store_cntr_rld_val(struct device *dev,
1066 struct device_attribute *attr,
1067 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001068{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001069 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001070 unsigned long val;
1071
1072 if (sscanf(buf, "%lx", &val) != 1)
1073 return -EINVAL;
1074
Pratik Patel0a10be22012-10-23 21:12:07 -07001075 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001076 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001077 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001078 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001079}
Pratik Patela9c0e062012-05-28 13:45:35 -07001080static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
1081 etm_store_cntr_rld_val);
1082
1083static ssize_t etm_show_cntr_event(struct device *dev,
1084 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001085{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001086 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001087 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001088
Pratik Patel0a10be22012-10-23 21:12:07 -07001089 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001090 val = drvdata->cntr_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001091 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001092 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1093}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001094
Pratik Patela9c0e062012-05-28 13:45:35 -07001095static ssize_t etm_store_cntr_event(struct device *dev,
1096 struct device_attribute *attr,
1097 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001098{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001099 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001100 unsigned long val;
1101
1102 if (sscanf(buf, "%lx", &val) != 1)
1103 return -EINVAL;
1104
Pratik Patel0a10be22012-10-23 21:12:07 -07001105 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001106 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001107 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001108 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001109}
Pratik Patela9c0e062012-05-28 13:45:35 -07001110static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1111 etm_store_cntr_event);
1112
1113static ssize_t etm_show_cntr_rld_event(struct device *dev,
1114 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001115{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001116 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001117 unsigned long val;
1118
Pratik Patel0a10be22012-10-23 21:12:07 -07001119 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001120 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001121 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001122 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1123}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001124
Pratik Patela9c0e062012-05-28 13:45:35 -07001125static ssize_t etm_store_cntr_rld_event(struct device *dev,
1126 struct device_attribute *attr,
1127 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001128{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001129 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001130 unsigned long val;
1131
1132 if (sscanf(buf, "%lx", &val) != 1)
1133 return -EINVAL;
1134
Pratik Patel0a10be22012-10-23 21:12:07 -07001135 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001136 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001137 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001138 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001139}
Pratik Patela9c0e062012-05-28 13:45:35 -07001140static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1141 etm_store_cntr_rld_event);
1142
1143static ssize_t etm_show_cntr_val(struct device *dev,
1144 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001145{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001146 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001147 unsigned long val;
1148
Pratik Patel0a10be22012-10-23 21:12:07 -07001149 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001150 val = drvdata->cntr_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001151 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001152 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1153}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001154
Pratik Patela9c0e062012-05-28 13:45:35 -07001155static ssize_t etm_store_cntr_val(struct device *dev,
1156 struct device_attribute *attr,
1157 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001158{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001159 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001160 unsigned long val;
1161
1162 if (sscanf(buf, "%lx", &val) != 1)
1163 return -EINVAL;
1164
Pratik Patel0a10be22012-10-23 21:12:07 -07001165 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001166 drvdata->cntr_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001167 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001168 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001169}
Pratik Patela9c0e062012-05-28 13:45:35 -07001170static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1171 etm_store_cntr_val);
1172
1173static ssize_t etm_show_seq_12_event(struct device *dev,
1174 struct device_attribute *attr, char *buf)
1175{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001176 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001177 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001178
Pratik Patela9c0e062012-05-28 13:45:35 -07001179 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1180}
1181
1182static ssize_t etm_store_seq_12_event(struct device *dev,
1183 struct device_attribute *attr,
1184 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001185{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001186 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001187 unsigned long val;
1188
Pratik Patela9c0e062012-05-28 13:45:35 -07001189 if (sscanf(buf, "%lx", &val) != 1)
1190 return -EINVAL;
1191
Pratik Patel16aefdb2012-05-30 10:41:23 -07001192 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001193 return size;
1194}
1195static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1196 etm_store_seq_12_event);
1197
1198static ssize_t etm_show_seq_21_event(struct device *dev,
1199 struct device_attribute *attr, char *buf)
1200{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001201 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001202 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001203
Pratik Patel6630ebe2012-03-06 16:44:22 -08001204 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1205}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001206
Pratik Patela9c0e062012-05-28 13:45:35 -07001207static ssize_t etm_store_seq_21_event(struct device *dev,
1208 struct device_attribute *attr,
1209 const char *buf, size_t size)
1210{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001211 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001212 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001213
Pratik Patela9c0e062012-05-28 13:45:35 -07001214 if (sscanf(buf, "%lx", &val) != 1)
1215 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001216
Pratik Patel16aefdb2012-05-30 10:41:23 -07001217 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001218 return size;
1219}
1220static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1221 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001222
Pratik Patela9c0e062012-05-28 13:45:35 -07001223static ssize_t etm_show_seq_23_event(struct device *dev,
1224 struct device_attribute *attr, char *buf)
1225{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001226 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001227 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001228
Pratik Patela9c0e062012-05-28 13:45:35 -07001229 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1230}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001231
Pratik Patela9c0e062012-05-28 13:45:35 -07001232static ssize_t etm_store_seq_23_event(struct device *dev,
1233 struct device_attribute *attr,
1234 const char *buf, size_t size)
1235{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001236 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001237 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001238
Pratik Patela9c0e062012-05-28 13:45:35 -07001239 if (sscanf(buf, "%lx", &val) != 1)
1240 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001241
Pratik Patel16aefdb2012-05-30 10:41:23 -07001242 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001243 return size;
1244}
1245static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1246 etm_store_seq_23_event);
1247
1248static ssize_t etm_show_seq_31_event(struct device *dev,
1249 struct device_attribute *attr, char *buf)
1250{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001251 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001252 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001253
Pratik Patela9c0e062012-05-28 13:45:35 -07001254 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1255}
1256
1257static ssize_t etm_store_seq_31_event(struct device *dev,
1258 struct device_attribute *attr,
1259 const char *buf, size_t size)
1260{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001261 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001262 unsigned long val;
1263
1264 if (sscanf(buf, "%lx", &val) != 1)
1265 return -EINVAL;
1266
Pratik Patel16aefdb2012-05-30 10:41:23 -07001267 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001268 return size;
1269}
1270static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1271 etm_store_seq_31_event);
1272
1273static ssize_t etm_show_seq_32_event(struct device *dev,
1274 struct device_attribute *attr, char *buf)
1275{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001276 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001277 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001278
Pratik Patela9c0e062012-05-28 13:45:35 -07001279 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1280}
1281
1282static ssize_t etm_store_seq_32_event(struct device *dev,
1283 struct device_attribute *attr,
1284 const char *buf, size_t size)
1285{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001286 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001287 unsigned long val;
1288
1289 if (sscanf(buf, "%lx", &val) != 1)
1290 return -EINVAL;
1291
Pratik Patel16aefdb2012-05-30 10:41:23 -07001292 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001293 return size;
1294}
1295static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1296 etm_store_seq_32_event);
1297
1298static ssize_t etm_show_seq_13_event(struct device *dev,
1299 struct device_attribute *attr, char *buf)
1300{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001301 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001302 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001303
Pratik Patela9c0e062012-05-28 13:45:35 -07001304 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1305}
1306
1307static ssize_t etm_store_seq_13_event(struct device *dev,
1308 struct device_attribute *attr,
1309 const char *buf, size_t size)
1310{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001311 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001312 unsigned long val;
1313
1314 if (sscanf(buf, "%lx", &val) != 1)
1315 return -EINVAL;
1316
Pratik Patel16aefdb2012-05-30 10:41:23 -07001317 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001318 return size;
1319}
1320static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1321 etm_store_seq_13_event);
1322
1323static ssize_t etm_show_seq_curr_state(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 Patel16aefdb2012-05-30 10:41:23 -07001327 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001328
Pratik Patela9c0e062012-05-28 13:45:35 -07001329 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1330}
1331
1332static ssize_t etm_store_seq_curr_state(struct device *dev,
1333 struct device_attribute *attr,
1334 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001335{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001336 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001337 unsigned long val;
1338
1339 if (sscanf(buf, "%lx", &val) != 1)
1340 return -EINVAL;
1341 if (val > ETM_SEQ_STATE_MAX_VAL)
1342 return -EINVAL;
1343
Pratik Patel16aefdb2012-05-30 10:41:23 -07001344 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001345 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001346}
Pratik Patela9c0e062012-05-28 13:45:35 -07001347static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1348 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001349
Pratik Patela9c0e062012-05-28 13:45:35 -07001350static ssize_t etm_show_ctxid_idx(struct device *dev,
1351 struct device_attribute *attr, char *buf)
1352{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001353 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001354 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001355
Pratik Patela9c0e062012-05-28 13:45:35 -07001356 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1357}
1358
1359static ssize_t etm_store_ctxid_idx(struct device *dev,
1360 struct device_attribute *attr,
1361 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001362{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001363 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001364 unsigned long val;
1365
1366 if (sscanf(buf, "%lx", &val) != 1)
1367 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001368 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001369 return -EINVAL;
1370
Pratik Patel0a10be22012-10-23 21:12:07 -07001371 /*
1372 * Use spinlock to ensure index doesn't change while it gets
1373 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001374 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001375 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001376 drvdata->ctxid_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001377 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001378 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001379}
Pratik Patela9c0e062012-05-28 13:45:35 -07001380static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1381 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001382
Pratik Patela9c0e062012-05-28 13:45:35 -07001383static ssize_t etm_show_ctxid_val(struct device *dev,
1384 struct device_attribute *attr, char *buf)
1385{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001386 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001387 unsigned long val;
1388
Pratik Patel0a10be22012-10-23 21:12:07 -07001389 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001390 val = drvdata->ctxid_val[drvdata->ctxid_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001391 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001392 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1393}
1394
1395static ssize_t etm_store_ctxid_val(struct device *dev,
1396 struct device_attribute *attr,
1397 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001398{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001399 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001400 unsigned long val;
1401
1402 if (sscanf(buf, "%lx", &val) != 1)
1403 return -EINVAL;
1404
Pratik Patel0a10be22012-10-23 21:12:07 -07001405 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001406 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001407 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001408 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001409}
Pratik Patela9c0e062012-05-28 13:45:35 -07001410static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1411 etm_store_ctxid_val);
1412
1413static ssize_t etm_show_ctxid_mask(struct device *dev,
1414 struct device_attribute *attr, char *buf)
1415{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001416 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001417 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001418
Pratik Patela9c0e062012-05-28 13:45:35 -07001419 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1420}
1421
1422static ssize_t etm_store_ctxid_mask(struct device *dev,
1423 struct device_attribute *attr,
1424 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001425{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001426 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001427 unsigned long val;
1428
Pratik Patela9c0e062012-05-28 13:45:35 -07001429 if (sscanf(buf, "%lx", &val) != 1)
1430 return -EINVAL;
1431
Pratik Patel16aefdb2012-05-30 10:41:23 -07001432 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001433 return size;
1434}
1435static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1436 etm_store_ctxid_mask);
1437
1438static ssize_t etm_show_sync_freq(struct device *dev,
1439 struct device_attribute *attr, char *buf)
1440{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001441 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001442 unsigned long val = drvdata->sync_freq;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001443
Pratik Patel6630ebe2012-03-06 16:44:22 -08001444 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1445}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001446
Pratik Patela9c0e062012-05-28 13:45:35 -07001447static ssize_t etm_store_sync_freq(struct device *dev,
1448 struct device_attribute *attr,
1449 const char *buf, size_t size)
1450{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001451 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001452 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001453
Pratik Patela9c0e062012-05-28 13:45:35 -07001454 if (sscanf(buf, "%lx", &val) != 1)
1455 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001456
Pratik Patel16aefdb2012-05-30 10:41:23 -07001457 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001458 return size;
1459}
1460static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1461 etm_store_sync_freq);
1462
1463static ssize_t etm_show_timestamp_event(struct device *dev,
1464 struct device_attribute *attr,
1465 char *buf)
1466{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001467 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001468 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001469
Pratik Patela9c0e062012-05-28 13:45:35 -07001470 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1471}
1472
1473static ssize_t etm_store_timestamp_event(struct device *dev,
1474 struct device_attribute *attr,
1475 const char *buf, size_t size)
1476{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001477 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001478 unsigned long val;
1479
1480 if (sscanf(buf, "%lx", &val) != 1)
1481 return -EINVAL;
1482
Pratik Patel16aefdb2012-05-30 10:41:23 -07001483 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001484 return size;
1485}
1486static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1487 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001488
Pratik Patel938e1ff2012-09-28 23:21:46 -07001489static ssize_t etm_show_pcsave(struct device *dev,
1490 struct device_attribute *attr, char *buf)
1491{
1492 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1493 unsigned long val;
1494
1495 val = drvdata->pcsave_enable;
1496 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1497}
1498
1499static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
1500{
Pratik Patel9dbfa372012-10-23 22:36:40 -07001501 int ret = 0;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001502
1503 ret = clk_prepare_enable(drvdata->clk);
1504 if (ret)
1505 return ret;
1506
Pratik Patel9dbfa372012-10-23 22:36:40 -07001507 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -07001508 spin_lock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001509 if (val) {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001510 if (drvdata->pcsave_enable)
1511 goto out;
1512
1513 ret = smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
1514 drvdata, 1);
1515 if (ret)
1516 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001517 drvdata->pcsave_enable = true;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001518
1519 dev_info(drvdata->dev, "PC save enabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001520 } else {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001521 if (!drvdata->pcsave_enable)
1522 goto out;
1523
1524 ret = smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
1525 drvdata, 1);
1526 if (ret)
1527 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001528 drvdata->pcsave_enable = false;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001529
1530 dev_info(drvdata->dev, "PC save disabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001531 }
Pratik Patel9dbfa372012-10-23 22:36:40 -07001532out:
Pratik Patel0a10be22012-10-23 21:12:07 -07001533 spin_unlock(&drvdata->spinlock);
Pratik Patel9dbfa372012-10-23 22:36:40 -07001534 put_online_cpus();
Pratik Patel938e1ff2012-09-28 23:21:46 -07001535
1536 clk_disable_unprepare(drvdata->clk);
Pratik Patel9dbfa372012-10-23 22:36:40 -07001537 return ret;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001538}
1539
1540static ssize_t etm_store_pcsave(struct device *dev,
1541 struct device_attribute *attr,
1542 const char *buf, size_t size)
1543{
1544 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1545 unsigned long val;
1546 int ret;
1547
1548 if (sscanf(buf, "%lx", &val) != 1)
1549 return -EINVAL;
1550
1551 ret = __etm_store_pcsave(drvdata, val);
1552 if (ret)
1553 return ret;
1554
1555 return size;
1556}
1557static DEVICE_ATTR(pcsave, S_IRUGO | S_IWUSR, etm_show_pcsave,
1558 etm_store_pcsave);
1559
Pratik Patel6630ebe2012-03-06 16:44:22 -08001560static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001561 &dev_attr_nr_addr_cmp.attr,
1562 &dev_attr_nr_cntr.attr,
1563 &dev_attr_nr_ctxid_cmp.attr,
1564 &dev_attr_reset.attr,
1565 &dev_attr_mode.attr,
1566 &dev_attr_trigger_event.attr,
1567 &dev_attr_enable_event.attr,
1568 &dev_attr_fifofull_level.attr,
1569 &dev_attr_addr_idx.attr,
1570 &dev_attr_addr_single.attr,
1571 &dev_attr_addr_range.attr,
1572 &dev_attr_addr_start.attr,
1573 &dev_attr_addr_stop.attr,
1574 &dev_attr_addr_acctype.attr,
1575 &dev_attr_cntr_idx.attr,
1576 &dev_attr_cntr_rld_val.attr,
1577 &dev_attr_cntr_event.attr,
1578 &dev_attr_cntr_rld_event.attr,
1579 &dev_attr_cntr_val.attr,
1580 &dev_attr_seq_12_event.attr,
1581 &dev_attr_seq_21_event.attr,
1582 &dev_attr_seq_23_event.attr,
1583 &dev_attr_seq_31_event.attr,
1584 &dev_attr_seq_32_event.attr,
1585 &dev_attr_seq_13_event.attr,
1586 &dev_attr_seq_curr_state.attr,
1587 &dev_attr_ctxid_idx.attr,
1588 &dev_attr_ctxid_val.attr,
1589 &dev_attr_ctxid_mask.attr,
1590 &dev_attr_sync_freq.attr,
1591 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001592 NULL,
1593};
1594
1595static struct attribute_group etm_attr_grp = {
1596 .attrs = etm_attrs,
1597};
1598
Pratik Patel3b0ca882012-06-01 16:54:14 -07001599static const struct attribute_group *etm_attr_grps[] = {
1600 &etm_attr_grp,
1601 NULL,
1602};
1603
1604/* Memory mapped writes to clear os lock not supported */
1605static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001606{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001607 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001608
Pratik Patel3b0ca882012-06-01 16:54:14 -07001609 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1610 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001611}
1612
Stephen Boyda9510502012-04-24 16:23:34 -07001613static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001614{
Pratik Patel61de7302012-03-07 12:06:10 -08001615 switch (arch) {
1616 case PFT_ARCH_V1_1:
1617 break;
1618 default:
1619 return false;
1620 }
1621 return true;
1622}
1623
Pratik Patele6e41da2012-09-12 12:50:29 -07001624static void __devinit etm_prepare_arch(struct etm_drvdata *drvdata)
1625{
1626 /* Unlock OS lock first to allow memory mapped reads and writes. This
1627 * is required for Krait pass1
1628 * */
1629 etm_os_unlock(NULL);
1630 smp_call_function(etm_os_unlock, NULL, 1);
1631}
1632
1633static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001634{
Pratik Patel61de7302012-03-07 12:06:10 -08001635 uint32_t etmidr;
1636 uint32_t etmccr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001637 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001638
Pratik Patel3b0ca882012-06-01 16:54:14 -07001639 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001640 /*
1641 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
1642 * memory mapped interface and so use it first to enable power/clock
1643 * to allow subsequent cp14 accesses.
1644 */
Pratik Patelef6da292012-09-17 17:37:19 -07001645 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -07001646 /*
1647 * Clear power down bit since when this bit is set writes to
1648 * certain registers might be ignored.
1649 */
1650 etm_clr_pwrdwn(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001651 /* Set prog bit. It will be set from reset but this is included to
1652 * ensure it is set
1653 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001654 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001655
1656 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001657 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001658 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001659
Pratik Patel3b0ca882012-06-01 16:54:14 -07001660 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001661 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1662 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1663 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1664 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1665 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001666
Pratik Pateld1d65c92012-09-25 23:37:43 -07001667 etm_set_pwrdwn(drvdata);
Pratik Patelef6da292012-09-17 17:37:19 -07001668 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001669 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001670}
1671
Pratik Patelc14b4df2012-09-05 18:07:59 -07001672static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1673{
1674 drvdata->arch = etm0drvdata->arch;
1675 drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
1676 drvdata->nr_cntr = etm0drvdata->nr_cntr;
1677 drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
1678 drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
1679 drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
1680}
1681
Pratik Patel3b0ca882012-06-01 16:54:14 -07001682static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001683{
1684 int i;
1685
1686 drvdata->trigger_event = 0x406F;
1687 drvdata->enable_event = 0x6F;
1688 drvdata->enable_ctrl1 = 0x1;
1689 drvdata->fifofull_level = 0x28;
1690 if (drvdata->nr_addr_cmp >= 2) {
1691 drvdata->addr_val[0] = (uint32_t) _stext;
1692 drvdata->addr_val[1] = (uint32_t) _etext;
1693 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1694 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1695 }
1696 for (i = 0; i < drvdata->nr_cntr; i++) {
1697 drvdata->cntr_event[i] = 0x406F;
1698 drvdata->cntr_rld_event[i] = 0x406F;
1699 }
1700 drvdata->seq_12_event = 0x406F;
1701 drvdata->seq_21_event = 0x406F;
1702 drvdata->seq_23_event = 0x406F;
1703 drvdata->seq_31_event = 0x406F;
1704 drvdata->seq_32_event = 0x406F;
1705 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001706 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1707 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1708 drvdata->sync_freq = 0x100;
1709 else
1710 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001711 drvdata->timestamp_event = 0x406F;
1712
1713 /* Overrides for Krait pass1 */
1714 if (cpu_is_krait_v1()) {
1715 /* Krait pass1 doesn't support include filtering and non-cycle
1716 * accurate tracing
1717 */
1718 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1719 drvdata->ctrl = 0x1000;
1720 drvdata->enable_ctrl1 = 0x1000000;
1721 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1722 drvdata->addr_val[i] = 0x0;
1723 drvdata->addr_acctype[i] = 0x0;
1724 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1725 }
1726 }
1727}
1728
Pratik Patel492b3012012-03-06 14:22:30 -08001729static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001730{
Pratik Patele5771792011-09-17 18:33:54 -07001731 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001732 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001733 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001734 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001735 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07001736 uint32_t reg_size;
1737 static int count;
1738 void *baddr;
1739 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001740 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001741
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001742 if (pdev->dev.of_node) {
1743 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1744 if (IS_ERR(pdata))
1745 return PTR_ERR(pdata);
1746 pdev->dev.platform_data = pdata;
1747 }
1748
Pratik Patel4a1b2522012-06-17 15:31:15 -07001749 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1750 if (!drvdata)
1751 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001752 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001753 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001754
Pratik Patel4a1b2522012-06-17 15:31:15 -07001755 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1756 if (!res)
1757 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07001758 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07001759
Pratik Patel4a1b2522012-06-17 15:31:15 -07001760 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1761 if (!drvdata->base)
1762 return -ENOMEM;
1763
Pratik Patel0a10be22012-10-23 21:12:07 -07001764 spin_lock_init(&drvdata->spinlock);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001765 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07001766
Pratik Patel4a1b2522012-06-17 15:31:15 -07001767 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001768 if (IS_ERR(drvdata->clk)) {
1769 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001770 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001771 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001772
Pratik Patel6fb38342012-06-03 14:51:38 -07001773 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001774 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001775 goto err0;
1776
Pratik Patel26477792012-09-07 01:35:36 -07001777 drvdata->cpu = count++;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001778
Pratik Patel16aefdb2012-05-30 10:41:23 -07001779 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001780 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001781 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001782
Pratik Patelc14b4df2012-09-05 18:07:59 -07001783 /* Use CPU0 to populate read-only configuration data for ETM0. For other
1784 * ETMs copy it over from ETM0.
1785 */
1786 if (drvdata->cpu == 0) {
Pratik Patele6e41da2012-09-12 12:50:29 -07001787 etm_prepare_arch(drvdata);
1788 smp_call_function_single(drvdata->cpu, etm_init_arch_data,
1789 drvdata, 1);
Pratik Patelc14b4df2012-09-05 18:07:59 -07001790 etm0drvdata = drvdata;
1791 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001792 etm_copy_arch_data(drvdata);
1793 }
1794 if (etm_arch_supported(drvdata->arch) == false) {
1795 ret = -EINVAL;
1796 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001797 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001798 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001799
Pratik Patel16aefdb2012-05-30 10:41:23 -07001800 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001801
Pratik Patel26477792012-09-07 01:35:36 -07001802 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
1803 if (baddr) {
1804 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
1805 dump.id = MSM_ETM0_REG + drvdata->cpu;
1806 dump.start_addr = virt_to_phys(baddr);
1807 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
1808 ret = msm_dump_table_register(&dump);
1809 if (ret) {
1810 devm_kfree(dev, baddr);
1811 dev_err(dev, "ETM REG dump setup failed\n");
1812 }
1813 } else {
1814 dev_err(dev, "ETM REG dump space allocation failed\n");
1815 }
1816
Pratik Patel4a1b2522012-06-17 15:31:15 -07001817 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001818 if (!desc) {
1819 ret = -ENOMEM;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001820 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001821 }
1822 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1823 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1824 desc->ops = &etm_cs_ops;
1825 desc->pdata = pdev->dev.platform_data;
1826 desc->dev = &pdev->dev;
1827 desc->groups = etm_attr_grps;
1828 desc->owner = THIS_MODULE;
1829 drvdata->csdev = coresight_register(desc);
1830 if (IS_ERR(drvdata->csdev)) {
1831 ret = PTR_ERR(drvdata->csdev);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001832 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001833 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001834
Pratik Patel938e1ff2012-09-28 23:21:46 -07001835 if (pdev->dev.of_node)
1836 drvdata->pcsave_impl = of_property_read_bool(pdev->dev.of_node,
1837 "qcom,pc-save");
1838 if (drvdata->pcsave_impl) {
1839 ret = device_create_file(&drvdata->csdev->dev,
1840 &dev_attr_pcsave);
1841 if (ret)
1842 dev_err(dev, "ETM pcsave dev node creation failed\n");
1843 }
1844
Pratik Patel4a1b2522012-06-17 15:31:15 -07001845 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001846
Pratik Patel3b0ca882012-06-01 16:54:14 -07001847 if (boot_enable)
1848 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001849
Pratik Patel938e1ff2012-09-28 23:21:46 -07001850 if (drvdata->pcsave_impl && boot_pcsave_enable)
1851 __etm_store_pcsave(drvdata, true);
1852
Pratik Patel7831c082011-06-08 21:44:37 -07001853 return 0;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001854err1:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001855 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001856err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001857 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07001858 return ret;
1859}
1860
Pratik Patelf6fe9182012-03-20 14:04:18 -07001861static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001862{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001863 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1864
Pratik Patel938e1ff2012-09-28 23:21:46 -07001865 device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001866 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001867 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07001868 return 0;
1869}
1870
Pratik Patel9eae4822012-05-14 17:34:53 -07001871static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001872 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001873 {}
1874};
1875
Pratik Patel492b3012012-03-06 14:22:30 -08001876static struct platform_driver etm_driver = {
1877 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001878 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001879 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001880 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001881 .owner = THIS_MODULE,
1882 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001883 },
1884};
1885
Pratik Patel492b3012012-03-06 14:22:30 -08001886int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001887{
Pratik Patel492b3012012-03-06 14:22:30 -08001888 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001889}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001890module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001891
Pratik Patelf6fe9182012-03-20 14:04:18 -07001892void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001893{
Pratik Patel492b3012012-03-06 14:22:30 -08001894 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001895}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001896module_exit(etm_exit);
1897
1898MODULE_LICENSE("GPL v2");
1899MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");