blob: 9f96b19f9196b8c597b19a0a328e9f7a8d497c5b [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 Patel97a08f32012-10-22 11:47:41 -0700200 bool os_unlock;
Pratik Patel61de7302012-03-07 12:06:10 -0800201 uint8_t nr_addr_cmp;
202 uint8_t nr_cntr;
203 uint8_t nr_ext_inp;
204 uint8_t nr_ext_out;
205 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800206 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800207 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800208 uint32_t ctrl;
209 uint32_t trigger_event;
210 uint32_t startstop_ctrl;
211 uint32_t enable_event;
212 uint32_t enable_ctrl1;
213 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800214 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800215 uint32_t addr_val[ETM_MAX_ADDR_CMP];
216 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800217 uint32_t addr_type[ETM_MAX_ADDR_CMP];
218 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800219 uint32_t cntr_rld_val[ETM_MAX_CNTR];
220 uint32_t cntr_event[ETM_MAX_CNTR];
221 uint32_t cntr_rld_event[ETM_MAX_CNTR];
222 uint32_t cntr_val[ETM_MAX_CNTR];
223 uint32_t seq_12_event;
224 uint32_t seq_21_event;
225 uint32_t seq_23_event;
226 uint32_t seq_31_event;
227 uint32_t seq_32_event;
228 uint32_t seq_13_event;
229 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800230 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800231 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
232 uint32_t ctxid_mask;
233 uint32_t sync_freq;
234 uint32_t timestamp_event;
Pratik Patel938e1ff2012-09-28 23:21:46 -0700235 bool pcsave_impl;
236 bool pcsave_enable;
Pratik Patelcd2452e2012-11-15 09:57:29 -0800237 bool pcsave_sticky_enable;
238 bool pcsave_boot_enable;
Pratik Patel7831c082011-06-08 21:44:37 -0700239};
240
Pratik Patel97a08f32012-10-22 11:47:41 -0700241static struct etm_drvdata *etmdrvdata[NR_CPUS];
242
243/*
244 * Memory mapped writes to clear os lock are not supported on Krait v1, v2
245 * and OS lock must be unlocked before any memory mapped access, otherwise
246 * memory mapped reads/writes will be invalid.
247 */
248static void etm_os_unlock(void *info)
249{
250 etm_writel_cp14(0x0, ETMOSLAR);
251 isb();
252}
Pratik Patelc14b4df2012-09-05 18:07:59 -0700253
Pratik Pateld1d65c92012-09-25 23:37:43 -0700254/*
255 * ETM clock is derived from the processor clock and gets enabled on a
256 * logical OR of below items on Krait (v2 onwards):
Pratik Patel17f3b822011-11-21 12:41:47 -0800257 * 1.CPMR[ETMCLKEN] is 1
258 * 2.ETMCR[PD] is 0
259 * 3.ETMPDCR[PU] is 1
260 * 4.Reset is asserted (core or debug)
261 * 5.APB memory mapped requests (eg. EDAP access)
262 *
263 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
264 * enables
265 *
Pratik Pateld1d65c92012-09-25 23:37:43 -0700266 * We rely on 5. to be able to access ETMCR/ETMPDCR and then use 2./3. above
267 * for ETM clock vote in the driver and the save-restore code uses 1. above
Pratik Patel17f3b822011-11-21 12:41:47 -0800268 * for its vote
269 */
Pratik Pateld1d65c92012-09-25 23:37:43 -0700270static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
271{
272 uint32_t etmcr;
273
274 /* ensure pending cp14 accesses complete before setting pwrdwn */
275 mb();
276 isb();
277 etmcr = etm_readl(drvdata, ETMCR);
278 etmcr |= BIT(0);
279 etm_writel(drvdata, etmcr, ETMCR);
280}
281
282static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
283{
284 uint32_t etmcr;
285
286 etmcr = etm_readl(drvdata, ETMCR);
287 etmcr &= ~BIT(0);
288 etm_writel(drvdata, etmcr, ETMCR);
289 /* ensure pwrup completes before subsequent cp14 accesses */
290 mb();
291 isb();
292}
293
Pratik Patelef6da292012-09-17 17:37:19 -0700294static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700295{
Pratik Patelef6da292012-09-17 17:37:19 -0700296 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700297
Pratik Patele6e41da2012-09-12 12:50:29 -0700298 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700299 etmpdcr |= BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700300 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
301 /* ensure pwrup completes before subsequent cp14 accesses */
302 mb();
303 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700304}
305
Pratik Patelef6da292012-09-17 17:37:19 -0700306static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700307{
Pratik Patelef6da292012-09-17 17:37:19 -0700308 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700309
Pratik Patele6e41da2012-09-12 12:50:29 -0700310 /* ensure pending cp14 accesses complete before clearing pwrup */
311 mb();
312 isb();
313 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700314 etmpdcr &= ~BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700315 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700316}
317
Pratik Patel3b0ca882012-06-01 16:54:14 -0700318static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700319{
320 uint32_t etmcr;
321 int count;
322
Pratik Patel3b0ca882012-06-01 16:54:14 -0700323 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700324 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700325 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700326 /* recommended by spec for cp14 accesses to ensure etmcr write is
327 * complete before polling etmsr
328 */
329 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700330 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700331 && count > 0; count--)
332 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800333 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700334 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700335}
336
Pratik Patel3b0ca882012-06-01 16:54:14 -0700337static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700338{
339 uint32_t etmcr;
340 int count;
341
Pratik Patel3b0ca882012-06-01 16:54:14 -0700342 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700343 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700344 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700345 /* recommended by spec for cp14 accesses to ensure etmcr write is
346 * complete before polling etmsr
347 */
348 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700349 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700350 && count > 0; count--)
351 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800352 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700353 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700354}
355
Pratik Patel938e1ff2012-09-28 23:21:46 -0700356static void etm_enable_pcsave(void *info)
357{
358 struct etm_drvdata *drvdata = info;
359
360 ETM_UNLOCK(drvdata);
361
Pratik Patel938e1ff2012-09-28 23:21:46 -0700362 /*
363 * ETMPDCR is only accessible via memory mapped interface and so use
364 * it first to enable power/clock to allow subsequent cp14 accesses.
365 */
366 etm_set_pwrup(drvdata);
367 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800368 etm_clr_pwrup(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700369
370 ETM_LOCK(drvdata);
371}
372
373static void etm_disable_pcsave(void *info)
374{
375 struct etm_drvdata *drvdata = info;
376
377 ETM_UNLOCK(drvdata);
378
Pratik Patelf95c5402012-11-05 18:21:08 -0800379 if (!drvdata->enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700380 etm_set_pwrdwn(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700381
382 ETM_LOCK(drvdata);
383}
384
Pratik Patel66e1a412012-09-06 11:07:06 -0700385static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700386{
Pratik Patel17f3b822011-11-21 12:41:47 -0800387 int i;
Pratik Pateld1d65c92012-09-25 23:37:43 -0700388 uint32_t etmcr;
Pratik Patel66e1a412012-09-06 11:07:06 -0700389 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700390
Pratik Patel3b0ca882012-06-01 16:54:14 -0700391 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700392 /*
393 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
394 * memory mapped interface and so use it first to enable power/clock
395 * to allow subsequent cp14 accesses.
396 */
Pratik Patelef6da292012-09-17 17:37:19 -0700397 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -0700398 /*
399 * Clear power down bit since when this bit is set writes to
Pratik Patelf3238df2012-10-19 16:19:12 -0700400 * certain registers might be ignored. This is also a pre-requisite
401 * for trace enable.
Pratik Pateld1d65c92012-09-25 23:37:43 -0700402 */
403 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800404 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700405 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700406
Pratik Pateld1d65c92012-09-25 23:37:43 -0700407 etmcr = etm_readl(drvdata, ETMCR);
408 etmcr &= (BIT(10) | BIT(0));
409 etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700410 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
411 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
412 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
413 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
414 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700415 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700416 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
417 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700418 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700419 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700420 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
421 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
422 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700423 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700424 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800425 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700426 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
427 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
428 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
429 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
430 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
431 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
432 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700433 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700434 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700435 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700436 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
437 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
438 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
439 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
440 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
441 etm_writel(drvdata, 0x00000000, ETMAUXCR);
442 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
443 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800444
Pratik Patel3b0ca882012-06-01 16:54:14 -0700445 etm_clr_prog(drvdata);
446 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700447
448 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700449}
450
Pratik Patel3b0ca882012-06-01 16:54:14 -0700451static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700452{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700453 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
454 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800455
Pratik Patel16aefdb2012-05-30 10:41:23 -0700456 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700457
Pratik Patel16aefdb2012-05-30 10:41:23 -0700458 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700459 if (ret)
460 goto err_clk;
461
Pratik Patel97a08f32012-10-22 11:47:41 -0700462 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -0700463 spin_lock(&drvdata->spinlock);
464
Pratik Patelf3238df2012-10-19 16:19:12 -0700465 /*
466 * Executing __etm_enable on the cpu whose ETM is being enabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700467 * ensures that register writes occur when cpu is powered.
468 */
Pratik Patel97a08f32012-10-22 11:47:41 -0700469 ret = smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
470 if (ret)
471 goto err;
Pratik Patelf3238df2012-10-19 16:19:12 -0700472 drvdata->enable = true;
Pratik Patel0a10be22012-10-23 21:12:07 -0700473
474 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700475 put_online_cpus();
Pratik Patel7831c082011-06-08 21:44:37 -0700476
Pratik Patel16aefdb2012-05-30 10:41:23 -0700477 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700478
Pratik Patel16aefdb2012-05-30 10:41:23 -0700479 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700480 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -0700481err:
482 spin_unlock(&drvdata->spinlock);
483 put_online_cpus();
484 clk_disable_unprepare(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700485err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700486 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800487 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700488}
489
Pratik Patel66e1a412012-09-06 11:07:06 -0700490static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700491{
Pratik Patel66e1a412012-09-06 11:07:06 -0700492 struct etm_drvdata *drvdata = info;
493
Pratik Patel3b0ca882012-06-01 16:54:14 -0700494 ETM_UNLOCK(drvdata);
495 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700496
Pratik Patel17f3b822011-11-21 12:41:47 -0800497 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700498 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700499
Pratik Patelf95c5402012-11-05 18:21:08 -0800500 if (!drvdata->pcsave_enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700501 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700502 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700503
504 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700505}
506
Pratik Patel3b0ca882012-06-01 16:54:14 -0700507static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700508{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700509 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800510
Pratik Patel16aefdb2012-05-30 10:41:23 -0700511 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700512
Pratik Patel97a08f32012-10-22 11:47:41 -0700513 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -0700514 spin_lock(&drvdata->spinlock);
515
Pratik Patelf3238df2012-10-19 16:19:12 -0700516 /*
517 * Executing __etm_disable on the cpu whose ETM is being disabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700518 * ensures that register writes occur when cpu is powered.
519 */
520 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patelf3238df2012-10-19 16:19:12 -0700521 drvdata->enable = false;
Pratik Patel0a10be22012-10-23 21:12:07 -0700522
523 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700524 put_online_cpus();
Pratik Patel7831c082011-06-08 21:44:37 -0700525
Pratik Patel16aefdb2012-05-30 10:41:23 -0700526 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700527
Pratik Patel16aefdb2012-05-30 10:41:23 -0700528 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700529
Pratik Patel16aefdb2012-05-30 10:41:23 -0700530 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700531}
532
Pratik Patel3b0ca882012-06-01 16:54:14 -0700533static const struct coresight_ops_source etm_source_ops = {
534 .enable = etm_enable,
535 .disable = etm_disable,
536};
Pratik Patel17f3b822011-11-21 12:41:47 -0800537
Pratik Patel3b0ca882012-06-01 16:54:14 -0700538static const struct coresight_ops etm_cs_ops = {
539 .source_ops = &etm_source_ops,
540};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800541
Pratik Patela9c0e062012-05-28 13:45:35 -0700542static ssize_t etm_show_nr_addr_cmp(struct device *dev,
543 struct device_attribute *attr, char *buf)
544{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700545 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700546 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700547
Pratik Patela9c0e062012-05-28 13:45:35 -0700548 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
549}
550static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
551
552static ssize_t etm_show_nr_cntr(struct device *dev,
553 struct device_attribute *attr, char *buf)
554{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700555 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700556 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700557
Pratik Patela9c0e062012-05-28 13:45:35 -0700558 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
559}
560static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
561
562static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
563 struct device_attribute *attr, char *buf)
564{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700565 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700566 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700567
Pratik Patela9c0e062012-05-28 13:45:35 -0700568 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
569}
570static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
571
572static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
573 char *buf)
574{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700575 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700576 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700577
Pratik Patela9c0e062012-05-28 13:45:35 -0700578 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
579}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800580
Pratik Pateld30deda2012-02-01 14:40:55 -0800581/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700582static ssize_t etm_store_reset(struct device *dev,
583 struct device_attribute *attr, const char *buf,
584 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800585{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700586 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800587 int i;
588 unsigned long val;
589
590 if (sscanf(buf, "%lx", &val) != 1)
591 return -EINVAL;
592
Pratik Patel0a10be22012-10-23 21:12:07 -0700593 spin_lock(&drvdata->spinlock);
Pratik Pateld30deda2012-02-01 14:40:55 -0800594 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700595 drvdata->mode = ETM_MODE_EXCLUDE;
596 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800597 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700598 drvdata->mode |= ETM_MODE_CYCACC;
599 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800600 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700601 drvdata->trigger_event = 0x406F;
602 drvdata->startstop_ctrl = 0x0;
603 drvdata->enable_event = 0x6F;
604 drvdata->enable_ctrl1 = 0x1000000;
605 drvdata->fifofull_level = 0x28;
606 drvdata->addr_idx = 0x0;
607 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
608 drvdata->addr_val[i] = 0x0;
609 drvdata->addr_acctype[i] = 0x0;
610 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800611 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700612 drvdata->cntr_idx = 0x0;
613 for (i = 0; i < drvdata->nr_cntr; i++) {
614 drvdata->cntr_rld_val[i] = 0x0;
615 drvdata->cntr_event[i] = 0x406F;
616 drvdata->cntr_rld_event[i] = 0x406F;
617 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800618 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700619 drvdata->seq_12_event = 0x406F;
620 drvdata->seq_21_event = 0x406F;
621 drvdata->seq_23_event = 0x406F;
622 drvdata->seq_31_event = 0x406F;
623 drvdata->seq_32_event = 0x406F;
624 drvdata->seq_13_event = 0x406F;
625 drvdata->seq_curr_state = 0x0;
626 drvdata->ctxid_idx = 0x0;
627 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
628 drvdata->ctxid_val[i] = 0x0;
629 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700630 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
631 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
632 drvdata->sync_freq = 0x100;
633 else
634 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700635 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800636 }
Pratik Patel0a10be22012-10-23 21:12:07 -0700637 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700638 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800639}
Pratik Patela9c0e062012-05-28 13:45:35 -0700640static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800641
Pratik Patela9c0e062012-05-28 13:45:35 -0700642static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
643 char *buf)
644{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700645 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700646 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700647
Pratik Patela9c0e062012-05-28 13:45:35 -0700648 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
649}
650
651static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
652 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800653{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700654 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800655 unsigned long val;
656
657 if (sscanf(buf, "%lx", &val) != 1)
658 return -EINVAL;
659
Pratik Patel0a10be22012-10-23 21:12:07 -0700660 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700661 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800662
Pratik Patel16aefdb2012-05-30 10:41:23 -0700663 if (drvdata->mode & ETM_MODE_EXCLUDE)
664 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800665 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700666 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800667
Pratik Patel16aefdb2012-05-30 10:41:23 -0700668 if (drvdata->mode & ETM_MODE_CYCACC)
669 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800670 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700671 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800672
Pratik Patel16aefdb2012-05-30 10:41:23 -0700673 if (drvdata->mode & ETM_MODE_STALL)
674 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800675 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700676 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800677
Pratik Patel16aefdb2012-05-30 10:41:23 -0700678 if (drvdata->mode & ETM_MODE_TIMESTAMP)
679 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800680 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700681 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700682
Pratik Patel16aefdb2012-05-30 10:41:23 -0700683 if (drvdata->mode & ETM_MODE_CTXID)
684 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800685 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700686 drvdata->ctrl &= ~(BIT(14) | BIT(15));
Pratik Patel0a10be22012-10-23 21:12:07 -0700687 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800688
Pratik Patela9c0e062012-05-28 13:45:35 -0700689 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800690}
Pratik Patela9c0e062012-05-28 13:45:35 -0700691static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800692
Pratik Patela9c0e062012-05-28 13:45:35 -0700693static ssize_t etm_show_trigger_event(struct device *dev,
694 struct device_attribute *attr, char *buf)
695{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700696 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700697 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700698
Pratik Patela9c0e062012-05-28 13:45:35 -0700699 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
700}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800701
Pratik Patela9c0e062012-05-28 13:45:35 -0700702static ssize_t etm_store_trigger_event(struct device *dev,
703 struct device_attribute *attr,
704 const char *buf, size_t size)
705{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700706 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700707 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800708
Pratik Patela9c0e062012-05-28 13:45:35 -0700709 if (sscanf(buf, "%lx", &val) != 1)
710 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800711
Pratik Patel16aefdb2012-05-30 10:41:23 -0700712 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700713 return size;
714}
715static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
716 etm_store_trigger_event);
717
718static ssize_t etm_show_enable_event(struct device *dev,
719 struct device_attribute *attr, char *buf)
720{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700721 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700722 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700723
Pratik Patela9c0e062012-05-28 13:45:35 -0700724 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
725}
726
727static ssize_t etm_store_enable_event(struct device *dev,
728 struct device_attribute *attr,
729 const char *buf, size_t size)
730{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700731 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700732 unsigned long val;
733
734 if (sscanf(buf, "%lx", &val) != 1)
735 return -EINVAL;
736
Pratik Patel16aefdb2012-05-30 10:41:23 -0700737 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700738 return size;
739}
740static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
741 etm_store_enable_event);
742
743static ssize_t etm_show_fifofull_level(struct device *dev,
744 struct device_attribute *attr, char *buf)
745{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700746 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700747 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700748
Pratik Patela9c0e062012-05-28 13:45:35 -0700749 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
750}
751
752static ssize_t etm_store_fifofull_level(struct device *dev,
753 struct device_attribute *attr,
754 const char *buf, size_t size)
755{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700756 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700757 unsigned long val;
758
759 if (sscanf(buf, "%lx", &val) != 1)
760 return -EINVAL;
761
Pratik Patel16aefdb2012-05-30 10:41:23 -0700762 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700763 return size;
764}
765static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
766 etm_store_fifofull_level);
767
768static ssize_t etm_show_addr_idx(struct device *dev,
769 struct device_attribute *attr, char *buf)
770{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700771 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700772 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700773
Pratik Patela9c0e062012-05-28 13:45:35 -0700774 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
775}
776
777static ssize_t etm_store_addr_idx(struct device *dev,
778 struct device_attribute *attr,
779 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800780{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700781 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800782 unsigned long val;
783
784 if (sscanf(buf, "%lx", &val) != 1)
785 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700786 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800787 return -EINVAL;
788
Pratik Patel0a10be22012-10-23 21:12:07 -0700789 /*
790 * Use spinlock to ensure index doesn't change while it gets
791 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -0800792 */
Pratik Patel0a10be22012-10-23 21:12:07 -0700793 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700794 drvdata->addr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -0700795 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700796 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800797}
Pratik Patela9c0e062012-05-28 13:45:35 -0700798static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
799 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800800
Pratik Patela9c0e062012-05-28 13:45:35 -0700801static ssize_t etm_show_addr_single(struct device *dev,
802 struct device_attribute *attr, char *buf)
803{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700804 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700805 unsigned long val;
806 uint8_t idx;
807
Pratik Patel0a10be22012-10-23 21:12:07 -0700808 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700809 idx = drvdata->addr_idx;
810 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
811 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700812 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700813 return -EPERM;
814 }
815
Pratik Patel16aefdb2012-05-30 10:41:23 -0700816 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700817 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700818 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
819}
820
821static ssize_t etm_store_addr_single(struct device *dev,
822 struct device_attribute *attr,
823 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800824{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700825 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800826 unsigned long val;
827 uint8_t idx;
828
829 if (sscanf(buf, "%lx", &val) != 1)
830 return -EINVAL;
831
Pratik Patel0a10be22012-10-23 21:12:07 -0700832 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700833 idx = drvdata->addr_idx;
834 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
835 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700836 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800837 return -EPERM;
838 }
839
Pratik Patel16aefdb2012-05-30 10:41:23 -0700840 drvdata->addr_val[idx] = val;
841 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
Pratik Patel0a10be22012-10-23 21:12:07 -0700842 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700843 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800844}
Pratik Patela9c0e062012-05-28 13:45:35 -0700845static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
846 etm_store_addr_single);
847
848static ssize_t etm_show_addr_range(struct device *dev,
849 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800850{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700851 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700852 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800853 uint8_t idx;
854
Pratik Patel0a10be22012-10-23 21:12:07 -0700855 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700856 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700857 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700858 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700859 return -EPERM;
860 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700861 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
862 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
863 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
864 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700865 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800866 return -EPERM;
867 }
868
Pratik Patel16aefdb2012-05-30 10:41:23 -0700869 val1 = drvdata->addr_val[idx];
870 val2 = drvdata->addr_val[idx + 1];
Pratik Patel0a10be22012-10-23 21:12:07 -0700871 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700872 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800873}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800874
Pratik Patela9c0e062012-05-28 13:45:35 -0700875static ssize_t etm_store_addr_range(struct device *dev,
876 struct device_attribute *attr,
877 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800878{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700879 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800880 unsigned long val1, val2;
881 uint8_t idx;
882
883 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
884 return -EINVAL;
885 /* lower address comparator cannot have a higher address value */
886 if (val1 > val2)
887 return -EINVAL;
888
Pratik Patel0a10be22012-10-23 21:12:07 -0700889 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700890 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800891 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700892 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800893 return -EPERM;
894 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700895 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
896 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
897 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
898 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700899 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800900 return -EPERM;
901 }
902
Pratik Patel16aefdb2012-05-30 10:41:23 -0700903 drvdata->addr_val[idx] = val1;
904 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
905 drvdata->addr_val[idx + 1] = val2;
906 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
907 drvdata->enable_ctrl1 |= (1 << (idx/2));
Pratik Patel0a10be22012-10-23 21:12:07 -0700908 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700909 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800910}
Pratik Patela9c0e062012-05-28 13:45:35 -0700911static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
912 etm_store_addr_range);
913
914static ssize_t etm_show_addr_start(struct device *dev,
915 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800916{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700917 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700918 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800919 uint8_t idx;
920
Pratik Patel0a10be22012-10-23 21:12:07 -0700921 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700922 idx = drvdata->addr_idx;
923 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
924 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700925 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800926 return -EPERM;
927 }
928
Pratik Patel16aefdb2012-05-30 10:41:23 -0700929 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700930 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700931 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800932}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800933
Pratik Patela9c0e062012-05-28 13:45:35 -0700934static ssize_t etm_store_addr_start(struct device *dev,
935 struct device_attribute *attr,
936 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800937{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700938 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800939 unsigned long val;
940 uint8_t idx;
941
942 if (sscanf(buf, "%lx", &val) != 1)
943 return -EINVAL;
944
Pratik Patel0a10be22012-10-23 21:12:07 -0700945 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700946 idx = drvdata->addr_idx;
947 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
948 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700949 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800950 return -EPERM;
951 }
952
Pratik Patel16aefdb2012-05-30 10:41:23 -0700953 drvdata->addr_val[idx] = val;
954 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
955 drvdata->startstop_ctrl |= (1 << idx);
956 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -0700957 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700958 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800959}
Pratik Patela9c0e062012-05-28 13:45:35 -0700960static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
961 etm_store_addr_start);
962
963static ssize_t etm_show_addr_stop(struct device *dev,
964 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800965{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700966 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800967 unsigned long val;
968 uint8_t idx;
969
Pratik Patel0a10be22012-10-23 21:12:07 -0700970 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700971 idx = drvdata->addr_idx;
972 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
973 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700974 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800975 return -EPERM;
976 }
977
Pratik Patel16aefdb2012-05-30 10:41:23 -0700978 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700979 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800980 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
981}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800982
Pratik Patela9c0e062012-05-28 13:45:35 -0700983static ssize_t etm_store_addr_stop(struct device *dev,
984 struct device_attribute *attr,
985 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800986{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700987 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800988 unsigned long val;
989 uint8_t idx;
990
991 if (sscanf(buf, "%lx", &val) != 1)
992 return -EINVAL;
993
Pratik Patel0a10be22012-10-23 21:12:07 -0700994 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700995 idx = drvdata->addr_idx;
996 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
997 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700998 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800999 return -EPERM;
1000 }
1001
Pratik Patel16aefdb2012-05-30 10:41:23 -07001002 drvdata->addr_val[idx] = val;
1003 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
1004 drvdata->startstop_ctrl |= (1 << (idx + 16));
1005 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -07001006 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001007 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001008}
Pratik Patela9c0e062012-05-28 13:45:35 -07001009static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
1010 etm_store_addr_stop);
1011
1012static ssize_t etm_show_addr_acctype(struct device *dev,
1013 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001014{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001015 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001016 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001017
Pratik Patel0a10be22012-10-23 21:12:07 -07001018 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001019 val = drvdata->addr_acctype[drvdata->addr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001020 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001021 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1022}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001023
Pratik Patela9c0e062012-05-28 13:45:35 -07001024static ssize_t etm_store_addr_acctype(struct device *dev,
1025 struct device_attribute *attr,
1026 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001027{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001028 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001029 unsigned long val;
1030
1031 if (sscanf(buf, "%lx", &val) != 1)
1032 return -EINVAL;
1033
Pratik Patel0a10be22012-10-23 21:12:07 -07001034 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001035 drvdata->addr_acctype[drvdata->addr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001036 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001037 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001038}
Pratik Patela9c0e062012-05-28 13:45:35 -07001039static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
1040 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001041
Pratik Patela9c0e062012-05-28 13:45:35 -07001042static ssize_t etm_show_cntr_idx(struct device *dev,
1043 struct device_attribute *attr, char *buf)
1044{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001045 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001046 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001047
Pratik Patel6630ebe2012-03-06 16:44:22 -08001048 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1049}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001050
Pratik Patela9c0e062012-05-28 13:45:35 -07001051static ssize_t etm_store_cntr_idx(struct device *dev,
1052 struct device_attribute *attr,
1053 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001054{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001055 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001056 unsigned long val;
1057
1058 if (sscanf(buf, "%lx", &val) != 1)
1059 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001060 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001061 return -EINVAL;
1062
Pratik Patel0a10be22012-10-23 21:12:07 -07001063 /*
1064 * Use spinlock to ensure index doesn't change while it gets
1065 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001066 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001067 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001068 drvdata->cntr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001069 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001070 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001071}
Pratik Patela9c0e062012-05-28 13:45:35 -07001072static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
1073 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001074
Pratik Patela9c0e062012-05-28 13:45:35 -07001075static ssize_t etm_show_cntr_rld_val(struct device *dev,
1076 struct device_attribute *attr, char *buf)
1077{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001078 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001079 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001080
Pratik Patel0a10be22012-10-23 21:12:07 -07001081 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001082 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001083 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001084 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1085}
1086
1087static ssize_t etm_store_cntr_rld_val(struct device *dev,
1088 struct device_attribute *attr,
1089 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001090{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001091 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001092 unsigned long val;
1093
1094 if (sscanf(buf, "%lx", &val) != 1)
1095 return -EINVAL;
1096
Pratik Patel0a10be22012-10-23 21:12:07 -07001097 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001098 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001099 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001100 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001101}
Pratik Patela9c0e062012-05-28 13:45:35 -07001102static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
1103 etm_store_cntr_rld_val);
1104
1105static ssize_t etm_show_cntr_event(struct device *dev,
1106 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001107{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001108 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001109 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001110
Pratik Patel0a10be22012-10-23 21:12:07 -07001111 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001112 val = drvdata->cntr_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001113 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001114 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1115}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001116
Pratik Patela9c0e062012-05-28 13:45:35 -07001117static ssize_t etm_store_cntr_event(struct device *dev,
1118 struct device_attribute *attr,
1119 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001120{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001121 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001122 unsigned long val;
1123
1124 if (sscanf(buf, "%lx", &val) != 1)
1125 return -EINVAL;
1126
Pratik Patel0a10be22012-10-23 21:12:07 -07001127 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001128 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001129 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001130 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001131}
Pratik Patela9c0e062012-05-28 13:45:35 -07001132static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1133 etm_store_cntr_event);
1134
1135static ssize_t etm_show_cntr_rld_event(struct device *dev,
1136 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001137{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001138 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001139 unsigned long val;
1140
Pratik Patel0a10be22012-10-23 21:12:07 -07001141 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001142 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001143 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001144 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1145}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001146
Pratik Patela9c0e062012-05-28 13:45:35 -07001147static ssize_t etm_store_cntr_rld_event(struct device *dev,
1148 struct device_attribute *attr,
1149 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001150{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001151 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001152 unsigned long val;
1153
1154 if (sscanf(buf, "%lx", &val) != 1)
1155 return -EINVAL;
1156
Pratik Patel0a10be22012-10-23 21:12:07 -07001157 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001158 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001159 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001160 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001161}
Pratik Patela9c0e062012-05-28 13:45:35 -07001162static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1163 etm_store_cntr_rld_event);
1164
1165static ssize_t etm_show_cntr_val(struct device *dev,
1166 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001167{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001168 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001169 unsigned long val;
1170
Pratik Patel0a10be22012-10-23 21:12:07 -07001171 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001172 val = drvdata->cntr_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001173 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001174 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1175}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001176
Pratik Patela9c0e062012-05-28 13:45:35 -07001177static ssize_t etm_store_cntr_val(struct device *dev,
1178 struct device_attribute *attr,
1179 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001180{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001181 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001182 unsigned long val;
1183
1184 if (sscanf(buf, "%lx", &val) != 1)
1185 return -EINVAL;
1186
Pratik Patel0a10be22012-10-23 21:12:07 -07001187 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001188 drvdata->cntr_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001189 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001190 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001191}
Pratik Patela9c0e062012-05-28 13:45:35 -07001192static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1193 etm_store_cntr_val);
1194
1195static ssize_t etm_show_seq_12_event(struct device *dev,
1196 struct device_attribute *attr, char *buf)
1197{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001198 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001199 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001200
Pratik Patela9c0e062012-05-28 13:45:35 -07001201 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1202}
1203
1204static ssize_t etm_store_seq_12_event(struct device *dev,
1205 struct device_attribute *attr,
1206 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001207{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001208 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001209 unsigned long val;
1210
Pratik Patela9c0e062012-05-28 13:45:35 -07001211 if (sscanf(buf, "%lx", &val) != 1)
1212 return -EINVAL;
1213
Pratik Patel16aefdb2012-05-30 10:41:23 -07001214 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001215 return size;
1216}
1217static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1218 etm_store_seq_12_event);
1219
1220static ssize_t etm_show_seq_21_event(struct device *dev,
1221 struct device_attribute *attr, char *buf)
1222{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001223 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001224 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001225
Pratik Patel6630ebe2012-03-06 16:44:22 -08001226 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1227}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001228
Pratik Patela9c0e062012-05-28 13:45:35 -07001229static ssize_t etm_store_seq_21_event(struct device *dev,
1230 struct device_attribute *attr,
1231 const char *buf, size_t size)
1232{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001233 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001234 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001235
Pratik Patela9c0e062012-05-28 13:45:35 -07001236 if (sscanf(buf, "%lx", &val) != 1)
1237 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001238
Pratik Patel16aefdb2012-05-30 10:41:23 -07001239 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001240 return size;
1241}
1242static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1243 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001244
Pratik Patela9c0e062012-05-28 13:45:35 -07001245static ssize_t etm_show_seq_23_event(struct device *dev,
1246 struct device_attribute *attr, char *buf)
1247{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001248 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001249 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001250
Pratik Patela9c0e062012-05-28 13:45:35 -07001251 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1252}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001253
Pratik Patela9c0e062012-05-28 13:45:35 -07001254static ssize_t etm_store_seq_23_event(struct device *dev,
1255 struct device_attribute *attr,
1256 const char *buf, size_t size)
1257{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001258 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001259 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001260
Pratik Patela9c0e062012-05-28 13:45:35 -07001261 if (sscanf(buf, "%lx", &val) != 1)
1262 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001263
Pratik Patel16aefdb2012-05-30 10:41:23 -07001264 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001265 return size;
1266}
1267static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1268 etm_store_seq_23_event);
1269
1270static ssize_t etm_show_seq_31_event(struct device *dev,
1271 struct device_attribute *attr, char *buf)
1272{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001273 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001274 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001275
Pratik Patela9c0e062012-05-28 13:45:35 -07001276 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1277}
1278
1279static ssize_t etm_store_seq_31_event(struct device *dev,
1280 struct device_attribute *attr,
1281 const char *buf, size_t size)
1282{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001283 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001284 unsigned long val;
1285
1286 if (sscanf(buf, "%lx", &val) != 1)
1287 return -EINVAL;
1288
Pratik Patel16aefdb2012-05-30 10:41:23 -07001289 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001290 return size;
1291}
1292static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1293 etm_store_seq_31_event);
1294
1295static ssize_t etm_show_seq_32_event(struct device *dev,
1296 struct device_attribute *attr, char *buf)
1297{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001298 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001299 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001300
Pratik Patela9c0e062012-05-28 13:45:35 -07001301 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1302}
1303
1304static ssize_t etm_store_seq_32_event(struct device *dev,
1305 struct device_attribute *attr,
1306 const char *buf, size_t size)
1307{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001308 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001309 unsigned long val;
1310
1311 if (sscanf(buf, "%lx", &val) != 1)
1312 return -EINVAL;
1313
Pratik Patel16aefdb2012-05-30 10:41:23 -07001314 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001315 return size;
1316}
1317static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1318 etm_store_seq_32_event);
1319
1320static ssize_t etm_show_seq_13_event(struct device *dev,
1321 struct device_attribute *attr, char *buf)
1322{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001323 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001324 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001325
Pratik Patela9c0e062012-05-28 13:45:35 -07001326 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1327}
1328
1329static ssize_t etm_store_seq_13_event(struct device *dev,
1330 struct device_attribute *attr,
1331 const char *buf, size_t size)
1332{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001333 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001334 unsigned long val;
1335
1336 if (sscanf(buf, "%lx", &val) != 1)
1337 return -EINVAL;
1338
Pratik Patel16aefdb2012-05-30 10:41:23 -07001339 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001340 return size;
1341}
1342static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1343 etm_store_seq_13_event);
1344
1345static ssize_t etm_show_seq_curr_state(struct device *dev,
1346 struct device_attribute *attr, char *buf)
1347{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001348 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001349 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001350
Pratik Patela9c0e062012-05-28 13:45:35 -07001351 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1352}
1353
1354static ssize_t etm_store_seq_curr_state(struct device *dev,
1355 struct device_attribute *attr,
1356 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001357{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001358 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001359 unsigned long val;
1360
1361 if (sscanf(buf, "%lx", &val) != 1)
1362 return -EINVAL;
1363 if (val > ETM_SEQ_STATE_MAX_VAL)
1364 return -EINVAL;
1365
Pratik Patel16aefdb2012-05-30 10:41:23 -07001366 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001367 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001368}
Pratik Patela9c0e062012-05-28 13:45:35 -07001369static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1370 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001371
Pratik Patela9c0e062012-05-28 13:45:35 -07001372static ssize_t etm_show_ctxid_idx(struct device *dev,
1373 struct device_attribute *attr, char *buf)
1374{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001375 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001376 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001377
Pratik Patela9c0e062012-05-28 13:45:35 -07001378 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1379}
1380
1381static ssize_t etm_store_ctxid_idx(struct device *dev,
1382 struct device_attribute *attr,
1383 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001384{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001385 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001386 unsigned long val;
1387
1388 if (sscanf(buf, "%lx", &val) != 1)
1389 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001390 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001391 return -EINVAL;
1392
Pratik Patel0a10be22012-10-23 21:12:07 -07001393 /*
1394 * Use spinlock to ensure index doesn't change while it gets
1395 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001396 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001397 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001398 drvdata->ctxid_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001399 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001400 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001401}
Pratik Patela9c0e062012-05-28 13:45:35 -07001402static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1403 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001404
Pratik Patela9c0e062012-05-28 13:45:35 -07001405static ssize_t etm_show_ctxid_val(struct device *dev,
1406 struct device_attribute *attr, char *buf)
1407{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001408 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001409 unsigned long val;
1410
Pratik Patel0a10be22012-10-23 21:12:07 -07001411 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001412 val = drvdata->ctxid_val[drvdata->ctxid_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001413 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001414 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1415}
1416
1417static ssize_t etm_store_ctxid_val(struct device *dev,
1418 struct device_attribute *attr,
1419 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001420{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001421 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001422 unsigned long val;
1423
1424 if (sscanf(buf, "%lx", &val) != 1)
1425 return -EINVAL;
1426
Pratik Patel0a10be22012-10-23 21:12:07 -07001427 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001428 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001429 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001430 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001431}
Pratik Patela9c0e062012-05-28 13:45:35 -07001432static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1433 etm_store_ctxid_val);
1434
1435static ssize_t etm_show_ctxid_mask(struct device *dev,
1436 struct device_attribute *attr, char *buf)
1437{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001438 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001439 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001440
Pratik Patela9c0e062012-05-28 13:45:35 -07001441 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1442}
1443
1444static ssize_t etm_store_ctxid_mask(struct device *dev,
1445 struct device_attribute *attr,
1446 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001447{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001448 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001449 unsigned long val;
1450
Pratik Patela9c0e062012-05-28 13:45:35 -07001451 if (sscanf(buf, "%lx", &val) != 1)
1452 return -EINVAL;
1453
Pratik Patel16aefdb2012-05-30 10:41:23 -07001454 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001455 return size;
1456}
1457static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1458 etm_store_ctxid_mask);
1459
1460static ssize_t etm_show_sync_freq(struct device *dev,
1461 struct device_attribute *attr, char *buf)
1462{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001463 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001464 unsigned long val = drvdata->sync_freq;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001465
Pratik Patel6630ebe2012-03-06 16:44:22 -08001466 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1467}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001468
Pratik Patela9c0e062012-05-28 13:45:35 -07001469static ssize_t etm_store_sync_freq(struct device *dev,
1470 struct device_attribute *attr,
1471 const char *buf, size_t size)
1472{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001473 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001474 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001475
Pratik Patela9c0e062012-05-28 13:45:35 -07001476 if (sscanf(buf, "%lx", &val) != 1)
1477 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001478
Pratik Patel16aefdb2012-05-30 10:41:23 -07001479 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001480 return size;
1481}
1482static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1483 etm_store_sync_freq);
1484
1485static ssize_t etm_show_timestamp_event(struct device *dev,
1486 struct device_attribute *attr,
1487 char *buf)
1488{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001489 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001490 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001491
Pratik Patela9c0e062012-05-28 13:45:35 -07001492 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1493}
1494
1495static ssize_t etm_store_timestamp_event(struct device *dev,
1496 struct device_attribute *attr,
1497 const char *buf, size_t size)
1498{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001499 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001500 unsigned long val;
1501
1502 if (sscanf(buf, "%lx", &val) != 1)
1503 return -EINVAL;
1504
Pratik Patel16aefdb2012-05-30 10:41:23 -07001505 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001506 return size;
1507}
1508static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1509 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001510
Pratik Patel938e1ff2012-09-28 23:21:46 -07001511static ssize_t etm_show_pcsave(struct device *dev,
1512 struct device_attribute *attr, char *buf)
1513{
1514 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1515 unsigned long val;
1516
1517 val = drvdata->pcsave_enable;
1518 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1519}
1520
Pratik Patelcd2452e2012-11-15 09:57:29 -08001521static int ____etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
Pratik Patel938e1ff2012-09-28 23:21:46 -07001522{
Pratik Patel9dbfa372012-10-23 22:36:40 -07001523 int ret = 0;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001524
1525 ret = clk_prepare_enable(drvdata->clk);
1526 if (ret)
1527 return ret;
1528
Pratik Patel0a10be22012-10-23 21:12:07 -07001529 spin_lock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001530 if (val) {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001531 if (drvdata->pcsave_enable)
1532 goto out;
1533
1534 ret = smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
1535 drvdata, 1);
1536 if (ret)
1537 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001538 drvdata->pcsave_enable = true;
Pratik Patelcd2452e2012-11-15 09:57:29 -08001539 drvdata->pcsave_sticky_enable = true;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001540
1541 dev_info(drvdata->dev, "PC save enabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001542 } else {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001543 if (!drvdata->pcsave_enable)
1544 goto out;
1545
1546 ret = smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
1547 drvdata, 1);
1548 if (ret)
1549 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001550 drvdata->pcsave_enable = false;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001551
1552 dev_info(drvdata->dev, "PC save disabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001553 }
Pratik Patel9dbfa372012-10-23 22:36:40 -07001554out:
Pratik Patel0a10be22012-10-23 21:12:07 -07001555 spin_unlock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001556
1557 clk_disable_unprepare(drvdata->clk);
Pratik Patel9dbfa372012-10-23 22:36:40 -07001558 return ret;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001559}
1560
Pratik Patelcd2452e2012-11-15 09:57:29 -08001561static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
1562{
1563 int ret;
1564
1565 get_online_cpus();
1566 ret = ____etm_store_pcsave(drvdata, val);
1567 put_online_cpus();
1568
1569 return ret;
1570}
1571
Pratik Patel938e1ff2012-09-28 23:21:46 -07001572static ssize_t etm_store_pcsave(struct device *dev,
1573 struct device_attribute *attr,
1574 const char *buf, size_t size)
1575{
1576 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1577 unsigned long val;
1578 int ret;
1579
1580 if (sscanf(buf, "%lx", &val) != 1)
1581 return -EINVAL;
1582
1583 ret = __etm_store_pcsave(drvdata, val);
1584 if (ret)
1585 return ret;
1586
1587 return size;
1588}
1589static DEVICE_ATTR(pcsave, S_IRUGO | S_IWUSR, etm_show_pcsave,
1590 etm_store_pcsave);
1591
Pratik Patel6630ebe2012-03-06 16:44:22 -08001592static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001593 &dev_attr_nr_addr_cmp.attr,
1594 &dev_attr_nr_cntr.attr,
1595 &dev_attr_nr_ctxid_cmp.attr,
1596 &dev_attr_reset.attr,
1597 &dev_attr_mode.attr,
1598 &dev_attr_trigger_event.attr,
1599 &dev_attr_enable_event.attr,
1600 &dev_attr_fifofull_level.attr,
1601 &dev_attr_addr_idx.attr,
1602 &dev_attr_addr_single.attr,
1603 &dev_attr_addr_range.attr,
1604 &dev_attr_addr_start.attr,
1605 &dev_attr_addr_stop.attr,
1606 &dev_attr_addr_acctype.attr,
1607 &dev_attr_cntr_idx.attr,
1608 &dev_attr_cntr_rld_val.attr,
1609 &dev_attr_cntr_event.attr,
1610 &dev_attr_cntr_rld_event.attr,
1611 &dev_attr_cntr_val.attr,
1612 &dev_attr_seq_12_event.attr,
1613 &dev_attr_seq_21_event.attr,
1614 &dev_attr_seq_23_event.attr,
1615 &dev_attr_seq_31_event.attr,
1616 &dev_attr_seq_32_event.attr,
1617 &dev_attr_seq_13_event.attr,
1618 &dev_attr_seq_curr_state.attr,
1619 &dev_attr_ctxid_idx.attr,
1620 &dev_attr_ctxid_val.attr,
1621 &dev_attr_ctxid_mask.attr,
1622 &dev_attr_sync_freq.attr,
1623 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001624 NULL,
1625};
1626
1627static struct attribute_group etm_attr_grp = {
1628 .attrs = etm_attrs,
1629};
1630
Pratik Patel3b0ca882012-06-01 16:54:14 -07001631static const struct attribute_group *etm_attr_grps[] = {
1632 &etm_attr_grp,
1633 NULL,
1634};
1635
Pratik Patel97a08f32012-10-22 11:47:41 -07001636static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
1637 void *hcpu)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001638{
Pratik Patel97a08f32012-10-22 11:47:41 -07001639 unsigned int cpu = (unsigned long)hcpu;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001640
Pratik Patel97a08f32012-10-22 11:47:41 -07001641 switch (action & (~CPU_TASKS_FROZEN)) {
1642 case CPU_STARTING:
1643 if (etmdrvdata[cpu] && !etmdrvdata[cpu]->os_unlock) {
1644 spin_lock(&etmdrvdata[cpu]->spinlock);
1645 etm_os_unlock(etmdrvdata[cpu]);
1646 etmdrvdata[cpu]->os_unlock = true;
1647 spin_unlock(&etmdrvdata[cpu]->spinlock);
1648 }
1649
1650 if (etmdrvdata[cpu] && etmdrvdata[cpu]->enable) {
1651 spin_lock(&etmdrvdata[cpu]->spinlock);
1652 __etm_enable(etmdrvdata[cpu]);
1653 spin_unlock(&etmdrvdata[cpu]->spinlock);
1654 }
1655 break;
1656
Pratik Patelcd2452e2012-11-15 09:57:29 -08001657 case CPU_ONLINE:
1658 if (etmdrvdata[cpu] && etmdrvdata[cpu]->pcsave_boot_enable &&
1659 !etmdrvdata[cpu]->pcsave_sticky_enable) {
1660 ____etm_store_pcsave(etmdrvdata[cpu], 1);
1661 }
1662 break;
1663
Pratik Patel97a08f32012-10-22 11:47:41 -07001664 case CPU_DYING:
1665 if (etmdrvdata[cpu] && etmdrvdata[cpu]->enable) {
1666 spin_lock(&etmdrvdata[cpu]->spinlock);
1667 __etm_disable(etmdrvdata[cpu]);
1668 spin_unlock(&etmdrvdata[cpu]->spinlock);
1669 }
1670 break;
1671 }
1672 return NOTIFY_OK;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001673}
1674
Pratik Patel97a08f32012-10-22 11:47:41 -07001675static struct notifier_block etm_cpu_notifier = {
1676 .notifier_call = etm_cpu_callback,
1677};
1678
Stephen Boyda9510502012-04-24 16:23:34 -07001679static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001680{
Pratik Patel61de7302012-03-07 12:06:10 -08001681 switch (arch) {
1682 case PFT_ARCH_V1_1:
1683 break;
1684 default:
1685 return false;
1686 }
1687 return true;
1688}
1689
Pratik Patele6e41da2012-09-12 12:50:29 -07001690static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001691{
Pratik Patel61de7302012-03-07 12:06:10 -08001692 uint32_t etmidr;
1693 uint32_t etmccr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001694 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001695
Pratik Patel3b0ca882012-06-01 16:54:14 -07001696 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001697 /*
1698 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
1699 * memory mapped interface and so use it first to enable power/clock
1700 * to allow subsequent cp14 accesses.
1701 */
Pratik Patelef6da292012-09-17 17:37:19 -07001702 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -07001703 /*
1704 * Clear power down bit since when this bit is set writes to
1705 * certain registers might be ignored.
1706 */
1707 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -08001708 etm_clr_pwrup(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001709 /* Set prog bit. It will be set from reset but this is included to
1710 * ensure it is set
1711 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001712 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001713
1714 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001715 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001716 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001717
Pratik Patel3b0ca882012-06-01 16:54:14 -07001718 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001719 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1720 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1721 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1722 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1723 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001724
Pratik Pateld1d65c92012-09-25 23:37:43 -07001725 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001726 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001727}
1728
Pratik Patelc14b4df2012-09-05 18:07:59 -07001729static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1730{
Pratik Patel97a08f32012-10-22 11:47:41 -07001731 drvdata->arch = etmdrvdata[0]->arch;
1732 drvdata->nr_addr_cmp = etmdrvdata[0]->nr_addr_cmp;
1733 drvdata->nr_cntr = etmdrvdata[0]->nr_cntr;
1734 drvdata->nr_ext_inp = etmdrvdata[0]->nr_ext_inp;
1735 drvdata->nr_ext_out = etmdrvdata[0]->nr_ext_out;
1736 drvdata->nr_ctxid_cmp = etmdrvdata[0]->nr_ctxid_cmp;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001737}
1738
Pratik Patel3b0ca882012-06-01 16:54:14 -07001739static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001740{
1741 int i;
1742
1743 drvdata->trigger_event = 0x406F;
1744 drvdata->enable_event = 0x6F;
1745 drvdata->enable_ctrl1 = 0x1;
1746 drvdata->fifofull_level = 0x28;
1747 if (drvdata->nr_addr_cmp >= 2) {
1748 drvdata->addr_val[0] = (uint32_t) _stext;
1749 drvdata->addr_val[1] = (uint32_t) _etext;
1750 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1751 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1752 }
1753 for (i = 0; i < drvdata->nr_cntr; i++) {
1754 drvdata->cntr_event[i] = 0x406F;
1755 drvdata->cntr_rld_event[i] = 0x406F;
1756 }
1757 drvdata->seq_12_event = 0x406F;
1758 drvdata->seq_21_event = 0x406F;
1759 drvdata->seq_23_event = 0x406F;
1760 drvdata->seq_31_event = 0x406F;
1761 drvdata->seq_32_event = 0x406F;
1762 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001763 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1764 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1765 drvdata->sync_freq = 0x100;
1766 else
1767 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001768 drvdata->timestamp_event = 0x406F;
1769
1770 /* Overrides for Krait pass1 */
1771 if (cpu_is_krait_v1()) {
1772 /* Krait pass1 doesn't support include filtering and non-cycle
1773 * accurate tracing
1774 */
1775 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1776 drvdata->ctrl = 0x1000;
1777 drvdata->enable_ctrl1 = 0x1000000;
1778 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1779 drvdata->addr_val[i] = 0x0;
1780 drvdata->addr_acctype[i] = 0x0;
1781 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1782 }
1783 }
1784}
1785
Pratik Patel492b3012012-03-06 14:22:30 -08001786static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001787{
Pratik Patele5771792011-09-17 18:33:54 -07001788 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001789 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001790 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001791 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001792 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07001793 uint32_t reg_size;
1794 static int count;
1795 void *baddr;
1796 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001797 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001798
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001799 if (pdev->dev.of_node) {
1800 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1801 if (IS_ERR(pdata))
1802 return PTR_ERR(pdata);
1803 pdev->dev.platform_data = pdata;
1804 }
1805
Pratik Patel4a1b2522012-06-17 15:31:15 -07001806 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1807 if (!drvdata)
1808 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001809 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001810 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001811
Pratik Patel4a1b2522012-06-17 15:31:15 -07001812 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1813 if (!res)
1814 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07001815 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07001816
Pratik Patel4a1b2522012-06-17 15:31:15 -07001817 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1818 if (!drvdata->base)
1819 return -ENOMEM;
1820
Pratik Patel0a10be22012-10-23 21:12:07 -07001821 spin_lock_init(&drvdata->spinlock);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001822 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07001823
Pratik Patel4a1b2522012-06-17 15:31:15 -07001824 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001825 if (IS_ERR(drvdata->clk)) {
1826 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001827 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001828 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001829
Pratik Patel6fb38342012-06-03 14:51:38 -07001830 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001831 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001832 goto err0;
1833
Pratik Patel16aefdb2012-05-30 10:41:23 -07001834 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001835 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001836 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001837
Pratik Patel97a08f32012-10-22 11:47:41 -07001838 drvdata->cpu = count++;
1839
1840 get_online_cpus();
1841 etmdrvdata[drvdata->cpu] = drvdata;
1842
1843 if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, NULL, 1))
1844 drvdata->os_unlock = true;
1845 /*
1846 * Use CPU0 to populate read-only configuration data for ETM0. For
1847 * other ETMs copy it over from ETM0.
Pratik Patelc14b4df2012-09-05 18:07:59 -07001848 */
1849 if (drvdata->cpu == 0) {
Pratik Patel97a08f32012-10-22 11:47:41 -07001850 register_hotcpu_notifier(&etm_cpu_notifier);
1851 if (smp_call_function_single(drvdata->cpu, etm_init_arch_data,
1852 drvdata, 1))
1853 dev_err(dev, "ETM arch init failed\n");
Pratik Patelc14b4df2012-09-05 18:07:59 -07001854 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001855 etm_copy_arch_data(drvdata);
1856 }
Pratik Patel97a08f32012-10-22 11:47:41 -07001857
1858 put_online_cpus();
1859
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001860 if (etm_arch_supported(drvdata->arch) == false) {
1861 ret = -EINVAL;
1862 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001863 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001864 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001865
Pratik Patel16aefdb2012-05-30 10:41:23 -07001866 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001867
Pratik Patel26477792012-09-07 01:35:36 -07001868 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
1869 if (baddr) {
1870 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
1871 dump.id = MSM_ETM0_REG + drvdata->cpu;
1872 dump.start_addr = virt_to_phys(baddr);
1873 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
1874 ret = msm_dump_table_register(&dump);
1875 if (ret) {
1876 devm_kfree(dev, baddr);
Pratik Patel97a08f32012-10-22 11:47:41 -07001877 dev_err(dev, "ETM REG dump setup failed/unsupported\n");
Pratik Patel26477792012-09-07 01:35:36 -07001878 }
1879 } else {
1880 dev_err(dev, "ETM REG dump space allocation failed\n");
1881 }
1882
Pratik Patel4a1b2522012-06-17 15:31:15 -07001883 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001884 if (!desc) {
1885 ret = -ENOMEM;
Pratik Patel97a08f32012-10-22 11:47:41 -07001886 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001887 }
1888 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1889 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1890 desc->ops = &etm_cs_ops;
1891 desc->pdata = pdev->dev.platform_data;
1892 desc->dev = &pdev->dev;
1893 desc->groups = etm_attr_grps;
1894 desc->owner = THIS_MODULE;
1895 drvdata->csdev = coresight_register(desc);
1896 if (IS_ERR(drvdata->csdev)) {
1897 ret = PTR_ERR(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07001898 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001899 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001900
Pratik Patel938e1ff2012-09-28 23:21:46 -07001901 if (pdev->dev.of_node)
1902 drvdata->pcsave_impl = of_property_read_bool(pdev->dev.of_node,
1903 "qcom,pc-save");
1904 if (drvdata->pcsave_impl) {
1905 ret = device_create_file(&drvdata->csdev->dev,
1906 &dev_attr_pcsave);
1907 if (ret)
1908 dev_err(dev, "ETM pcsave dev node creation failed\n");
1909 }
1910
Pratik Patel4a1b2522012-06-17 15:31:15 -07001911 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001912
Pratik Patel3b0ca882012-06-01 16:54:14 -07001913 if (boot_enable)
1914 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001915
Pratik Patelcd2452e2012-11-15 09:57:29 -08001916 if (drvdata->pcsave_impl && boot_pcsave_enable) {
1917 __etm_store_pcsave(drvdata, 1);
1918 drvdata->pcsave_boot_enable = true;
1919 }
Pratik Patel938e1ff2012-09-28 23:21:46 -07001920
Pratik Patel7831c082011-06-08 21:44:37 -07001921 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -07001922err2:
1923 if (drvdata->cpu == 0)
1924 unregister_hotcpu_notifier(&etm_cpu_notifier);
1925 wake_lock_destroy(&drvdata->wake_lock);
1926 return ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001927err1:
Pratik Patel97a08f32012-10-22 11:47:41 -07001928 if (drvdata->cpu == 0)
1929 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001930 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001931err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001932 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07001933 return ret;
1934}
1935
Pratik Patelf6fe9182012-03-20 14:04:18 -07001936static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001937{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001938 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1939
Pratik Patel938e1ff2012-09-28 23:21:46 -07001940 device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001941 coresight_unregister(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07001942 if (drvdata->cpu == 0)
1943 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001944 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07001945 return 0;
1946}
1947
Pratik Patel9eae4822012-05-14 17:34:53 -07001948static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001949 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001950 {}
1951};
1952
Pratik Patel492b3012012-03-06 14:22:30 -08001953static struct platform_driver etm_driver = {
1954 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001955 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001956 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001957 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001958 .owner = THIS_MODULE,
1959 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001960 },
1961};
1962
Pratik Patel492b3012012-03-06 14:22:30 -08001963int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001964{
Pratik Patel492b3012012-03-06 14:22:30 -08001965 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001966}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001967module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001968
Pratik Patelf6fe9182012-03-20 14:04:18 -07001969void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001970{
Pratik Patel492b3012012-03-06 14:22:30 -08001971 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001972}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001973module_exit(etm_exit);
1974
1975MODULE_LICENSE("GPL v2");
1976MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");