blob: f3fe70f73f5312c36fd6d7c0886b7aa1b135fabc [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 Patel7831c082011-06-08 21:44:37 -0700237};
238
Pratik Patel97a08f32012-10-22 11:47:41 -0700239static struct etm_drvdata *etmdrvdata[NR_CPUS];
240
241/*
242 * Memory mapped writes to clear os lock are not supported on Krait v1, v2
243 * and OS lock must be unlocked before any memory mapped access, otherwise
244 * memory mapped reads/writes will be invalid.
245 */
246static void etm_os_unlock(void *info)
247{
248 etm_writel_cp14(0x0, ETMOSLAR);
249 isb();
250}
Pratik Patelc14b4df2012-09-05 18:07:59 -0700251
Pratik Pateld1d65c92012-09-25 23:37:43 -0700252/*
253 * ETM clock is derived from the processor clock and gets enabled on a
254 * logical OR of below items on Krait (v2 onwards):
Pratik Patel17f3b822011-11-21 12:41:47 -0800255 * 1.CPMR[ETMCLKEN] is 1
256 * 2.ETMCR[PD] is 0
257 * 3.ETMPDCR[PU] is 1
258 * 4.Reset is asserted (core or debug)
259 * 5.APB memory mapped requests (eg. EDAP access)
260 *
261 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
262 * enables
263 *
Pratik Pateld1d65c92012-09-25 23:37:43 -0700264 * We rely on 5. to be able to access ETMCR/ETMPDCR and then use 2./3. above
265 * for ETM clock vote in the driver and the save-restore code uses 1. above
Pratik Patel17f3b822011-11-21 12:41:47 -0800266 * for its vote
267 */
Pratik Pateld1d65c92012-09-25 23:37:43 -0700268static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
269{
270 uint32_t etmcr;
271
272 /* ensure pending cp14 accesses complete before setting pwrdwn */
273 mb();
274 isb();
275 etmcr = etm_readl(drvdata, ETMCR);
276 etmcr |= BIT(0);
277 etm_writel(drvdata, etmcr, ETMCR);
278}
279
280static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
281{
282 uint32_t etmcr;
283
284 etmcr = etm_readl(drvdata, ETMCR);
285 etmcr &= ~BIT(0);
286 etm_writel(drvdata, etmcr, ETMCR);
287 /* ensure pwrup completes before subsequent cp14 accesses */
288 mb();
289 isb();
290}
291
Pratik Patelef6da292012-09-17 17:37:19 -0700292static void etm_set_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700293{
Pratik Patelef6da292012-09-17 17:37:19 -0700294 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700295
Pratik Patele6e41da2012-09-12 12:50:29 -0700296 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700297 etmpdcr |= BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700298 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
299 /* ensure pwrup completes before subsequent cp14 accesses */
300 mb();
301 isb();
Pratik Patel7831c082011-06-08 21:44:37 -0700302}
303
Pratik Patelef6da292012-09-17 17:37:19 -0700304static void etm_clr_pwrup(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700305{
Pratik Patelef6da292012-09-17 17:37:19 -0700306 uint32_t etmpdcr;
Pratik Patel7831c082011-06-08 21:44:37 -0700307
Pratik Patele6e41da2012-09-12 12:50:29 -0700308 /* ensure pending cp14 accesses complete before clearing pwrup */
309 mb();
310 isb();
311 etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
Pratik Patelef6da292012-09-17 17:37:19 -0700312 etmpdcr &= ~BIT(3);
Pratik Patele6e41da2012-09-12 12:50:29 -0700313 etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700314}
315
Pratik Patel3b0ca882012-06-01 16:54:14 -0700316static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700317{
318 uint32_t etmcr;
319 int count;
320
Pratik Patel3b0ca882012-06-01 16:54:14 -0700321 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700322 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700323 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700324 /* recommended by spec for cp14 accesses to ensure etmcr write is
325 * complete before polling etmsr
326 */
327 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700328 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700329 && count > 0; count--)
330 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800331 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700332 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700333}
334
Pratik Patel3b0ca882012-06-01 16:54:14 -0700335static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700336{
337 uint32_t etmcr;
338 int count;
339
Pratik Patel3b0ca882012-06-01 16:54:14 -0700340 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700341 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700342 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patele6e41da2012-09-12 12:50:29 -0700343 /* recommended by spec for cp14 accesses to ensure etmcr write is
344 * complete before polling etmsr
345 */
346 isb();
Pratik Patel3b0ca882012-06-01 16:54:14 -0700347 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700348 && count > 0; count--)
349 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800350 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700351 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700352}
353
Pratik Patel938e1ff2012-09-28 23:21:46 -0700354static void etm_enable_pcsave(void *info)
355{
356 struct etm_drvdata *drvdata = info;
357
358 ETM_UNLOCK(drvdata);
359
Pratik Patel938e1ff2012-09-28 23:21:46 -0700360 /*
361 * ETMPDCR is only accessible via memory mapped interface and so use
362 * it first to enable power/clock to allow subsequent cp14 accesses.
363 */
364 etm_set_pwrup(drvdata);
365 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800366 etm_clr_pwrup(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700367
368 ETM_LOCK(drvdata);
369}
370
371static void etm_disable_pcsave(void *info)
372{
373 struct etm_drvdata *drvdata = info;
374
375 ETM_UNLOCK(drvdata);
376
Pratik Patelf95c5402012-11-05 18:21:08 -0800377 if (!drvdata->enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700378 etm_set_pwrdwn(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700379
380 ETM_LOCK(drvdata);
381}
382
Pratik Patel66e1a412012-09-06 11:07:06 -0700383static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700384{
Pratik Patel17f3b822011-11-21 12:41:47 -0800385 int i;
Pratik Pateld1d65c92012-09-25 23:37:43 -0700386 uint32_t etmcr;
Pratik Patel66e1a412012-09-06 11:07:06 -0700387 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700388
Pratik Patel3b0ca882012-06-01 16:54:14 -0700389 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -0700390 /*
391 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
392 * memory mapped interface and so use it first to enable power/clock
393 * to allow subsequent cp14 accesses.
394 */
Pratik Patelef6da292012-09-17 17:37:19 -0700395 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -0700396 /*
397 * Clear power down bit since when this bit is set writes to
Pratik Patelf3238df2012-10-19 16:19:12 -0700398 * certain registers might be ignored. This is also a pre-requisite
399 * for trace enable.
Pratik Pateld1d65c92012-09-25 23:37:43 -0700400 */
401 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -0800402 etm_clr_pwrup(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700403 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700404
Pratik Pateld1d65c92012-09-25 23:37:43 -0700405 etmcr = etm_readl(drvdata, ETMCR);
406 etmcr &= (BIT(10) | BIT(0));
407 etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700408 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
409 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
410 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
411 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
412 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700413 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700414 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
415 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700416 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700417 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700418 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
419 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
420 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700421 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700422 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800423 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700424 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
425 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
426 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
427 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
428 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
429 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
430 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700431 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700432 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700433 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700434 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
435 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
436 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
437 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
438 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
439 etm_writel(drvdata, 0x00000000, ETMAUXCR);
440 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
441 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800442
Pratik Patel3b0ca882012-06-01 16:54:14 -0700443 etm_clr_prog(drvdata);
444 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700445
446 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700447}
448
Pratik Patel3b0ca882012-06-01 16:54:14 -0700449static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700450{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700451 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
452 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800453
Pratik Patel16aefdb2012-05-30 10:41:23 -0700454 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700455
Pratik Patel16aefdb2012-05-30 10:41:23 -0700456 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700457 if (ret)
458 goto err_clk;
459
Pratik Patel97a08f32012-10-22 11:47:41 -0700460 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -0700461 spin_lock(&drvdata->spinlock);
462
Pratik Patelf3238df2012-10-19 16:19:12 -0700463 /*
464 * Executing __etm_enable on the cpu whose ETM is being enabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700465 * ensures that register writes occur when cpu is powered.
466 */
Pratik Patel97a08f32012-10-22 11:47:41 -0700467 ret = smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
468 if (ret)
469 goto err;
Pratik Patelf3238df2012-10-19 16:19:12 -0700470 drvdata->enable = true;
Pratik Patel0a10be22012-10-23 21:12:07 -0700471
472 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700473 put_online_cpus();
Pratik Patel7831c082011-06-08 21:44:37 -0700474
Pratik Patel16aefdb2012-05-30 10:41:23 -0700475 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700476
Pratik Patel16aefdb2012-05-30 10:41:23 -0700477 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700478 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -0700479err:
480 spin_unlock(&drvdata->spinlock);
481 put_online_cpus();
482 clk_disable_unprepare(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700483err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700484 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800485 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700486}
487
Pratik Patel66e1a412012-09-06 11:07:06 -0700488static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700489{
Pratik Patel66e1a412012-09-06 11:07:06 -0700490 struct etm_drvdata *drvdata = info;
491
Pratik Patel3b0ca882012-06-01 16:54:14 -0700492 ETM_UNLOCK(drvdata);
493 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700494
Pratik Patel17f3b822011-11-21 12:41:47 -0800495 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700496 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700497
Pratik Patelf95c5402012-11-05 18:21:08 -0800498 if (!drvdata->pcsave_enable)
Pratik Patelf3238df2012-10-19 16:19:12 -0700499 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700500 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700501
502 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700503}
504
Pratik Patel3b0ca882012-06-01 16:54:14 -0700505static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700506{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700507 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800508
Pratik Patel16aefdb2012-05-30 10:41:23 -0700509 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700510
Pratik Patel97a08f32012-10-22 11:47:41 -0700511 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -0700512 spin_lock(&drvdata->spinlock);
513
Pratik Patelf3238df2012-10-19 16:19:12 -0700514 /*
515 * Executing __etm_disable on the cpu whose ETM is being disabled
Pratik Patel66e1a412012-09-06 11:07:06 -0700516 * ensures that register writes occur when cpu is powered.
517 */
518 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patelf3238df2012-10-19 16:19:12 -0700519 drvdata->enable = false;
Pratik Patel0a10be22012-10-23 21:12:07 -0700520
521 spin_unlock(&drvdata->spinlock);
Pratik Patel97a08f32012-10-22 11:47:41 -0700522 put_online_cpus();
Pratik Patel7831c082011-06-08 21:44:37 -0700523
Pratik Patel16aefdb2012-05-30 10:41:23 -0700524 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700525
Pratik Patel16aefdb2012-05-30 10:41:23 -0700526 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700527
Pratik Patel16aefdb2012-05-30 10:41:23 -0700528 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700529}
530
Pratik Patel3b0ca882012-06-01 16:54:14 -0700531static const struct coresight_ops_source etm_source_ops = {
532 .enable = etm_enable,
533 .disable = etm_disable,
534};
Pratik Patel17f3b822011-11-21 12:41:47 -0800535
Pratik Patel3b0ca882012-06-01 16:54:14 -0700536static const struct coresight_ops etm_cs_ops = {
537 .source_ops = &etm_source_ops,
538};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800539
Pratik Patela9c0e062012-05-28 13:45:35 -0700540static ssize_t etm_show_nr_addr_cmp(struct device *dev,
541 struct device_attribute *attr, char *buf)
542{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700543 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700544 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700545
Pratik Patela9c0e062012-05-28 13:45:35 -0700546 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
547}
548static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
549
550static ssize_t etm_show_nr_cntr(struct device *dev,
551 struct device_attribute *attr, char *buf)
552{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700553 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700554 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700555
Pratik Patela9c0e062012-05-28 13:45:35 -0700556 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
557}
558static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
559
560static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
561 struct device_attribute *attr, char *buf)
562{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700563 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700564 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700565
Pratik Patela9c0e062012-05-28 13:45:35 -0700566 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
567}
568static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
569
570static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
571 char *buf)
572{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700573 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700574 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700575
Pratik Patela9c0e062012-05-28 13:45:35 -0700576 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
577}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800578
Pratik Pateld30deda2012-02-01 14:40:55 -0800579/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700580static ssize_t etm_store_reset(struct device *dev,
581 struct device_attribute *attr, const char *buf,
582 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800583{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700584 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800585 int i;
586 unsigned long val;
587
588 if (sscanf(buf, "%lx", &val) != 1)
589 return -EINVAL;
590
Pratik Patel0a10be22012-10-23 21:12:07 -0700591 spin_lock(&drvdata->spinlock);
Pratik Pateld30deda2012-02-01 14:40:55 -0800592 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700593 drvdata->mode = ETM_MODE_EXCLUDE;
594 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800595 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700596 drvdata->mode |= ETM_MODE_CYCACC;
597 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800598 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700599 drvdata->trigger_event = 0x406F;
600 drvdata->startstop_ctrl = 0x0;
601 drvdata->enable_event = 0x6F;
602 drvdata->enable_ctrl1 = 0x1000000;
603 drvdata->fifofull_level = 0x28;
604 drvdata->addr_idx = 0x0;
605 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
606 drvdata->addr_val[i] = 0x0;
607 drvdata->addr_acctype[i] = 0x0;
608 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800609 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700610 drvdata->cntr_idx = 0x0;
611 for (i = 0; i < drvdata->nr_cntr; i++) {
612 drvdata->cntr_rld_val[i] = 0x0;
613 drvdata->cntr_event[i] = 0x406F;
614 drvdata->cntr_rld_event[i] = 0x406F;
615 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800616 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700617 drvdata->seq_12_event = 0x406F;
618 drvdata->seq_21_event = 0x406F;
619 drvdata->seq_23_event = 0x406F;
620 drvdata->seq_31_event = 0x406F;
621 drvdata->seq_32_event = 0x406F;
622 drvdata->seq_13_event = 0x406F;
623 drvdata->seq_curr_state = 0x0;
624 drvdata->ctxid_idx = 0x0;
625 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
626 drvdata->ctxid_val[i] = 0x0;
627 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700628 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
629 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
630 drvdata->sync_freq = 0x100;
631 else
632 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700633 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800634 }
Pratik Patel0a10be22012-10-23 21:12:07 -0700635 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700636 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800637}
Pratik Patela9c0e062012-05-28 13:45:35 -0700638static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800639
Pratik Patela9c0e062012-05-28 13:45:35 -0700640static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
641 char *buf)
642{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700643 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700644 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700645
Pratik Patela9c0e062012-05-28 13:45:35 -0700646 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
647}
648
649static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
650 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800651{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700652 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800653 unsigned long val;
654
655 if (sscanf(buf, "%lx", &val) != 1)
656 return -EINVAL;
657
Pratik Patel0a10be22012-10-23 21:12:07 -0700658 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700659 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800660
Pratik Patel16aefdb2012-05-30 10:41:23 -0700661 if (drvdata->mode & ETM_MODE_EXCLUDE)
662 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800663 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700664 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800665
Pratik Patel16aefdb2012-05-30 10:41:23 -0700666 if (drvdata->mode & ETM_MODE_CYCACC)
667 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800668 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700669 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800670
Pratik Patel16aefdb2012-05-30 10:41:23 -0700671 if (drvdata->mode & ETM_MODE_STALL)
672 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800673 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700674 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800675
Pratik Patel16aefdb2012-05-30 10:41:23 -0700676 if (drvdata->mode & ETM_MODE_TIMESTAMP)
677 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800678 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700679 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700680
Pratik Patel16aefdb2012-05-30 10:41:23 -0700681 if (drvdata->mode & ETM_MODE_CTXID)
682 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800683 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700684 drvdata->ctrl &= ~(BIT(14) | BIT(15));
Pratik Patel0a10be22012-10-23 21:12:07 -0700685 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800686
Pratik Patela9c0e062012-05-28 13:45:35 -0700687 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800688}
Pratik Patela9c0e062012-05-28 13:45:35 -0700689static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800690
Pratik Patela9c0e062012-05-28 13:45:35 -0700691static ssize_t etm_show_trigger_event(struct device *dev,
692 struct device_attribute *attr, char *buf)
693{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700694 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700695 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700696
Pratik Patela9c0e062012-05-28 13:45:35 -0700697 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
698}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800699
Pratik Patela9c0e062012-05-28 13:45:35 -0700700static ssize_t etm_store_trigger_event(struct device *dev,
701 struct device_attribute *attr,
702 const char *buf, size_t size)
703{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700704 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700705 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800706
Pratik Patela9c0e062012-05-28 13:45:35 -0700707 if (sscanf(buf, "%lx", &val) != 1)
708 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800709
Pratik Patel16aefdb2012-05-30 10:41:23 -0700710 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700711 return size;
712}
713static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
714 etm_store_trigger_event);
715
716static ssize_t etm_show_enable_event(struct device *dev,
717 struct device_attribute *attr, char *buf)
718{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700719 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700720 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700721
Pratik Patela9c0e062012-05-28 13:45:35 -0700722 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
723}
724
725static ssize_t etm_store_enable_event(struct device *dev,
726 struct device_attribute *attr,
727 const char *buf, size_t size)
728{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700729 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700730 unsigned long val;
731
732 if (sscanf(buf, "%lx", &val) != 1)
733 return -EINVAL;
734
Pratik Patel16aefdb2012-05-30 10:41:23 -0700735 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700736 return size;
737}
738static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
739 etm_store_enable_event);
740
741static ssize_t etm_show_fifofull_level(struct device *dev,
742 struct device_attribute *attr, char *buf)
743{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700744 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700745 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700746
Pratik Patela9c0e062012-05-28 13:45:35 -0700747 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
748}
749
750static ssize_t etm_store_fifofull_level(struct device *dev,
751 struct device_attribute *attr,
752 const char *buf, size_t size)
753{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700754 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700755 unsigned long val;
756
757 if (sscanf(buf, "%lx", &val) != 1)
758 return -EINVAL;
759
Pratik Patel16aefdb2012-05-30 10:41:23 -0700760 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700761 return size;
762}
763static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
764 etm_store_fifofull_level);
765
766static ssize_t etm_show_addr_idx(struct device *dev,
767 struct device_attribute *attr, char *buf)
768{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700769 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700770 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700771
Pratik Patela9c0e062012-05-28 13:45:35 -0700772 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
773}
774
775static ssize_t etm_store_addr_idx(struct device *dev,
776 struct device_attribute *attr,
777 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800778{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700779 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800780 unsigned long val;
781
782 if (sscanf(buf, "%lx", &val) != 1)
783 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700784 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800785 return -EINVAL;
786
Pratik Patel0a10be22012-10-23 21:12:07 -0700787 /*
788 * Use spinlock to ensure index doesn't change while it gets
789 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -0800790 */
Pratik Patel0a10be22012-10-23 21:12:07 -0700791 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700792 drvdata->addr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -0700793 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700794 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800795}
Pratik Patela9c0e062012-05-28 13:45:35 -0700796static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
797 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800798
Pratik Patela9c0e062012-05-28 13:45:35 -0700799static ssize_t etm_show_addr_single(struct device *dev,
800 struct device_attribute *attr, char *buf)
801{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700802 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700803 unsigned long val;
804 uint8_t idx;
805
Pratik Patel0a10be22012-10-23 21:12:07 -0700806 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700807 idx = drvdata->addr_idx;
808 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
809 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700810 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700811 return -EPERM;
812 }
813
Pratik Patel16aefdb2012-05-30 10:41:23 -0700814 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700815 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700816 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
817}
818
819static ssize_t etm_store_addr_single(struct device *dev,
820 struct device_attribute *attr,
821 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800822{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700823 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800824 unsigned long val;
825 uint8_t idx;
826
827 if (sscanf(buf, "%lx", &val) != 1)
828 return -EINVAL;
829
Pratik Patel0a10be22012-10-23 21:12:07 -0700830 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700831 idx = drvdata->addr_idx;
832 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
833 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700834 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800835 return -EPERM;
836 }
837
Pratik Patel16aefdb2012-05-30 10:41:23 -0700838 drvdata->addr_val[idx] = val;
839 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
Pratik Patel0a10be22012-10-23 21:12:07 -0700840 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700841 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800842}
Pratik Patela9c0e062012-05-28 13:45:35 -0700843static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
844 etm_store_addr_single);
845
846static ssize_t etm_show_addr_range(struct device *dev,
847 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800848{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700849 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700850 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800851 uint8_t idx;
852
Pratik Patel0a10be22012-10-23 21:12:07 -0700853 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700854 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700855 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700856 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700857 return -EPERM;
858 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700859 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
860 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
861 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
862 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700863 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800864 return -EPERM;
865 }
866
Pratik Patel16aefdb2012-05-30 10:41:23 -0700867 val1 = drvdata->addr_val[idx];
868 val2 = drvdata->addr_val[idx + 1];
Pratik Patel0a10be22012-10-23 21:12:07 -0700869 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700870 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800871}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800872
Pratik Patela9c0e062012-05-28 13:45:35 -0700873static ssize_t etm_store_addr_range(struct device *dev,
874 struct device_attribute *attr,
875 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800876{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700877 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800878 unsigned long val1, val2;
879 uint8_t idx;
880
881 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
882 return -EINVAL;
883 /* lower address comparator cannot have a higher address value */
884 if (val1 > val2)
885 return -EINVAL;
886
Pratik Patel0a10be22012-10-23 21:12:07 -0700887 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700888 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800889 if (idx % 2 != 0) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700890 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800891 return -EPERM;
892 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700893 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
894 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
895 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
896 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700897 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800898 return -EPERM;
899 }
900
Pratik Patel16aefdb2012-05-30 10:41:23 -0700901 drvdata->addr_val[idx] = val1;
902 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
903 drvdata->addr_val[idx + 1] = val2;
904 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
905 drvdata->enable_ctrl1 |= (1 << (idx/2));
Pratik Patel0a10be22012-10-23 21:12:07 -0700906 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700907 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800908}
Pratik Patela9c0e062012-05-28 13:45:35 -0700909static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
910 etm_store_addr_range);
911
912static ssize_t etm_show_addr_start(struct device *dev,
913 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800914{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700915 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700916 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800917 uint8_t idx;
918
Pratik Patel0a10be22012-10-23 21:12:07 -0700919 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700920 idx = drvdata->addr_idx;
921 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
922 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700923 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800924 return -EPERM;
925 }
926
Pratik Patel16aefdb2012-05-30 10:41:23 -0700927 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700928 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700929 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800930}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800931
Pratik Patela9c0e062012-05-28 13:45:35 -0700932static ssize_t etm_store_addr_start(struct device *dev,
933 struct device_attribute *attr,
934 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800935{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700936 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800937 unsigned long val;
938 uint8_t idx;
939
940 if (sscanf(buf, "%lx", &val) != 1)
941 return -EINVAL;
942
Pratik Patel0a10be22012-10-23 21:12:07 -0700943 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700944 idx = drvdata->addr_idx;
945 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
946 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700947 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800948 return -EPERM;
949 }
950
Pratik Patel16aefdb2012-05-30 10:41:23 -0700951 drvdata->addr_val[idx] = val;
952 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
953 drvdata->startstop_ctrl |= (1 << idx);
954 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -0700955 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -0700956 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800957}
Pratik Patela9c0e062012-05-28 13:45:35 -0700958static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
959 etm_store_addr_start);
960
961static ssize_t etm_show_addr_stop(struct device *dev,
962 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800963{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700964 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800965 unsigned long val;
966 uint8_t idx;
967
Pratik Patel0a10be22012-10-23 21:12:07 -0700968 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700969 idx = drvdata->addr_idx;
970 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
971 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700972 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800973 return -EPERM;
974 }
975
Pratik Patel16aefdb2012-05-30 10:41:23 -0700976 val = drvdata->addr_val[idx];
Pratik Patel0a10be22012-10-23 21:12:07 -0700977 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800978 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
979}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800980
Pratik Patela9c0e062012-05-28 13:45:35 -0700981static ssize_t etm_store_addr_stop(struct device *dev,
982 struct device_attribute *attr,
983 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800984{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700985 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800986 unsigned long val;
987 uint8_t idx;
988
989 if (sscanf(buf, "%lx", &val) != 1)
990 return -EINVAL;
991
Pratik Patel0a10be22012-10-23 21:12:07 -0700992 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700993 idx = drvdata->addr_idx;
994 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
995 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
Pratik Patel0a10be22012-10-23 21:12:07 -0700996 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800997 return -EPERM;
998 }
999
Pratik Patel16aefdb2012-05-30 10:41:23 -07001000 drvdata->addr_val[idx] = val;
1001 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
1002 drvdata->startstop_ctrl |= (1 << (idx + 16));
1003 drvdata->enable_ctrl1 |= BIT(25);
Pratik Patel0a10be22012-10-23 21:12:07 -07001004 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001005 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001006}
Pratik Patela9c0e062012-05-28 13:45:35 -07001007static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
1008 etm_store_addr_stop);
1009
1010static ssize_t etm_show_addr_acctype(struct device *dev,
1011 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001012{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001013 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001014 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001015
Pratik Patel0a10be22012-10-23 21:12:07 -07001016 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001017 val = drvdata->addr_acctype[drvdata->addr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001018 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001019 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1020}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001021
Pratik Patela9c0e062012-05-28 13:45:35 -07001022static ssize_t etm_store_addr_acctype(struct device *dev,
1023 struct device_attribute *attr,
1024 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001025{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001026 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001027 unsigned long val;
1028
1029 if (sscanf(buf, "%lx", &val) != 1)
1030 return -EINVAL;
1031
Pratik Patel0a10be22012-10-23 21:12:07 -07001032 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001033 drvdata->addr_acctype[drvdata->addr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001034 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001035 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001036}
Pratik Patela9c0e062012-05-28 13:45:35 -07001037static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
1038 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001039
Pratik Patela9c0e062012-05-28 13:45:35 -07001040static ssize_t etm_show_cntr_idx(struct device *dev,
1041 struct device_attribute *attr, char *buf)
1042{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001043 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001044 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001045
Pratik Patel6630ebe2012-03-06 16:44:22 -08001046 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1047}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001048
Pratik Patela9c0e062012-05-28 13:45:35 -07001049static ssize_t etm_store_cntr_idx(struct device *dev,
1050 struct device_attribute *attr,
1051 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001052{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001053 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001054 unsigned long val;
1055
1056 if (sscanf(buf, "%lx", &val) != 1)
1057 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001058 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001059 return -EINVAL;
1060
Pratik Patel0a10be22012-10-23 21:12:07 -07001061 /*
1062 * Use spinlock to ensure index doesn't change while it gets
1063 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001064 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001065 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001066 drvdata->cntr_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001067 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001068 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001069}
Pratik Patela9c0e062012-05-28 13:45:35 -07001070static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
1071 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001072
Pratik Patela9c0e062012-05-28 13:45:35 -07001073static ssize_t etm_show_cntr_rld_val(struct device *dev,
1074 struct device_attribute *attr, char *buf)
1075{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001076 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001077 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001078
Pratik Patel0a10be22012-10-23 21:12:07 -07001079 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001080 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001081 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001082 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1083}
1084
1085static ssize_t etm_store_cntr_rld_val(struct device *dev,
1086 struct device_attribute *attr,
1087 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001088{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001089 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001090 unsigned long val;
1091
1092 if (sscanf(buf, "%lx", &val) != 1)
1093 return -EINVAL;
1094
Pratik Patel0a10be22012-10-23 21:12:07 -07001095 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001096 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001097 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001098 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001099}
Pratik Patela9c0e062012-05-28 13:45:35 -07001100static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
1101 etm_store_cntr_rld_val);
1102
1103static ssize_t etm_show_cntr_event(struct device *dev,
1104 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001105{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001106 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001107 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001108
Pratik Patel0a10be22012-10-23 21:12:07 -07001109 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001110 val = drvdata->cntr_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001111 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001112 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1113}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001114
Pratik Patela9c0e062012-05-28 13:45:35 -07001115static ssize_t etm_store_cntr_event(struct device *dev,
1116 struct device_attribute *attr,
1117 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001118{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001119 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001120 unsigned long val;
1121
1122 if (sscanf(buf, "%lx", &val) != 1)
1123 return -EINVAL;
1124
Pratik Patel0a10be22012-10-23 21:12:07 -07001125 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001126 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001127 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001128 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001129}
Pratik Patela9c0e062012-05-28 13:45:35 -07001130static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1131 etm_store_cntr_event);
1132
1133static ssize_t etm_show_cntr_rld_event(struct device *dev,
1134 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001135{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001136 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001137 unsigned long val;
1138
Pratik Patel0a10be22012-10-23 21:12:07 -07001139 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001140 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001141 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001142 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1143}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001144
Pratik Patela9c0e062012-05-28 13:45:35 -07001145static ssize_t etm_store_cntr_rld_event(struct device *dev,
1146 struct device_attribute *attr,
1147 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001148{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001149 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001150 unsigned long val;
1151
1152 if (sscanf(buf, "%lx", &val) != 1)
1153 return -EINVAL;
1154
Pratik Patel0a10be22012-10-23 21:12:07 -07001155 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001156 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
Pratik Patel0a10be22012-10-23 21:12:07 -07001157 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001158 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001159}
Pratik Patela9c0e062012-05-28 13:45:35 -07001160static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1161 etm_store_cntr_rld_event);
1162
1163static ssize_t etm_show_cntr_val(struct device *dev,
1164 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001165{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001166 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001167 unsigned long val;
1168
Pratik Patel0a10be22012-10-23 21:12:07 -07001169 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001170 val = drvdata->cntr_val[drvdata->cntr_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001171 spin_unlock(&drvdata->spinlock);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001172 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1173}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001174
Pratik Patela9c0e062012-05-28 13:45:35 -07001175static ssize_t etm_store_cntr_val(struct device *dev,
1176 struct device_attribute *attr,
1177 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001178{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001179 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001180 unsigned long val;
1181
1182 if (sscanf(buf, "%lx", &val) != 1)
1183 return -EINVAL;
1184
Pratik Patel0a10be22012-10-23 21:12:07 -07001185 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001186 drvdata->cntr_val[drvdata->cntr_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001187 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001188 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001189}
Pratik Patela9c0e062012-05-28 13:45:35 -07001190static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1191 etm_store_cntr_val);
1192
1193static ssize_t etm_show_seq_12_event(struct device *dev,
1194 struct device_attribute *attr, char *buf)
1195{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001196 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001197 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001198
Pratik Patela9c0e062012-05-28 13:45:35 -07001199 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1200}
1201
1202static ssize_t etm_store_seq_12_event(struct device *dev,
1203 struct device_attribute *attr,
1204 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001205{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001206 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001207 unsigned long val;
1208
Pratik Patela9c0e062012-05-28 13:45:35 -07001209 if (sscanf(buf, "%lx", &val) != 1)
1210 return -EINVAL;
1211
Pratik Patel16aefdb2012-05-30 10:41:23 -07001212 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001213 return size;
1214}
1215static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1216 etm_store_seq_12_event);
1217
1218static ssize_t etm_show_seq_21_event(struct device *dev,
1219 struct device_attribute *attr, char *buf)
1220{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001221 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001222 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001223
Pratik Patel6630ebe2012-03-06 16:44:22 -08001224 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1225}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001226
Pratik Patela9c0e062012-05-28 13:45:35 -07001227static ssize_t etm_store_seq_21_event(struct device *dev,
1228 struct device_attribute *attr,
1229 const char *buf, size_t size)
1230{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001231 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001232 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001233
Pratik Patela9c0e062012-05-28 13:45:35 -07001234 if (sscanf(buf, "%lx", &val) != 1)
1235 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001236
Pratik Patel16aefdb2012-05-30 10:41:23 -07001237 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001238 return size;
1239}
1240static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1241 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001242
Pratik Patela9c0e062012-05-28 13:45:35 -07001243static ssize_t etm_show_seq_23_event(struct device *dev,
1244 struct device_attribute *attr, char *buf)
1245{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001246 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001247 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001248
Pratik Patela9c0e062012-05-28 13:45:35 -07001249 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1250}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001251
Pratik Patela9c0e062012-05-28 13:45:35 -07001252static ssize_t etm_store_seq_23_event(struct device *dev,
1253 struct device_attribute *attr,
1254 const char *buf, size_t size)
1255{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001256 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001257 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001258
Pratik Patela9c0e062012-05-28 13:45:35 -07001259 if (sscanf(buf, "%lx", &val) != 1)
1260 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001261
Pratik Patel16aefdb2012-05-30 10:41:23 -07001262 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001263 return size;
1264}
1265static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1266 etm_store_seq_23_event);
1267
1268static ssize_t etm_show_seq_31_event(struct device *dev,
1269 struct device_attribute *attr, char *buf)
1270{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001271 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001272 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001273
Pratik Patela9c0e062012-05-28 13:45:35 -07001274 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1275}
1276
1277static ssize_t etm_store_seq_31_event(struct device *dev,
1278 struct device_attribute *attr,
1279 const char *buf, size_t size)
1280{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001281 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001282 unsigned long val;
1283
1284 if (sscanf(buf, "%lx", &val) != 1)
1285 return -EINVAL;
1286
Pratik Patel16aefdb2012-05-30 10:41:23 -07001287 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001288 return size;
1289}
1290static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1291 etm_store_seq_31_event);
1292
1293static ssize_t etm_show_seq_32_event(struct device *dev,
1294 struct device_attribute *attr, char *buf)
1295{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001296 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001297 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001298
Pratik Patela9c0e062012-05-28 13:45:35 -07001299 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1300}
1301
1302static ssize_t etm_store_seq_32_event(struct device *dev,
1303 struct device_attribute *attr,
1304 const char *buf, size_t size)
1305{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001306 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001307 unsigned long val;
1308
1309 if (sscanf(buf, "%lx", &val) != 1)
1310 return -EINVAL;
1311
Pratik Patel16aefdb2012-05-30 10:41:23 -07001312 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001313 return size;
1314}
1315static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1316 etm_store_seq_32_event);
1317
1318static ssize_t etm_show_seq_13_event(struct device *dev,
1319 struct device_attribute *attr, char *buf)
1320{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001321 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001322 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001323
Pratik Patela9c0e062012-05-28 13:45:35 -07001324 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1325}
1326
1327static ssize_t etm_store_seq_13_event(struct device *dev,
1328 struct device_attribute *attr,
1329 const char *buf, size_t size)
1330{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001331 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001332 unsigned long val;
1333
1334 if (sscanf(buf, "%lx", &val) != 1)
1335 return -EINVAL;
1336
Pratik Patel16aefdb2012-05-30 10:41:23 -07001337 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001338 return size;
1339}
1340static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1341 etm_store_seq_13_event);
1342
1343static ssize_t etm_show_seq_curr_state(struct device *dev,
1344 struct device_attribute *attr, char *buf)
1345{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001346 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001347 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001348
Pratik Patela9c0e062012-05-28 13:45:35 -07001349 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1350}
1351
1352static ssize_t etm_store_seq_curr_state(struct device *dev,
1353 struct device_attribute *attr,
1354 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001355{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001356 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001357 unsigned long val;
1358
1359 if (sscanf(buf, "%lx", &val) != 1)
1360 return -EINVAL;
1361 if (val > ETM_SEQ_STATE_MAX_VAL)
1362 return -EINVAL;
1363
Pratik Patel16aefdb2012-05-30 10:41:23 -07001364 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001365 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001366}
Pratik Patela9c0e062012-05-28 13:45:35 -07001367static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1368 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001369
Pratik Patela9c0e062012-05-28 13:45:35 -07001370static ssize_t etm_show_ctxid_idx(struct device *dev,
1371 struct device_attribute *attr, char *buf)
1372{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001373 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001374 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001375
Pratik Patela9c0e062012-05-28 13:45:35 -07001376 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1377}
1378
1379static ssize_t etm_store_ctxid_idx(struct device *dev,
1380 struct device_attribute *attr,
1381 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001382{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001383 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001384 unsigned long val;
1385
1386 if (sscanf(buf, "%lx", &val) != 1)
1387 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001388 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001389 return -EINVAL;
1390
Pratik Patel0a10be22012-10-23 21:12:07 -07001391 /*
1392 * Use spinlock to ensure index doesn't change while it gets
1393 * dereferenced multiple times within a spinlock block elsewhere.
Pratik Patel6630ebe2012-03-06 16:44:22 -08001394 */
Pratik Patel0a10be22012-10-23 21:12:07 -07001395 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001396 drvdata->ctxid_idx = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001397 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001398 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001399}
Pratik Patela9c0e062012-05-28 13:45:35 -07001400static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1401 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001402
Pratik Patela9c0e062012-05-28 13:45:35 -07001403static ssize_t etm_show_ctxid_val(struct device *dev,
1404 struct device_attribute *attr, char *buf)
1405{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001406 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001407 unsigned long val;
1408
Pratik Patel0a10be22012-10-23 21:12:07 -07001409 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001410 val = drvdata->ctxid_val[drvdata->ctxid_idx];
Pratik Patel0a10be22012-10-23 21:12:07 -07001411 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001412 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1413}
1414
1415static ssize_t etm_store_ctxid_val(struct device *dev,
1416 struct device_attribute *attr,
1417 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001418{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001419 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001420 unsigned long val;
1421
1422 if (sscanf(buf, "%lx", &val) != 1)
1423 return -EINVAL;
1424
Pratik Patel0a10be22012-10-23 21:12:07 -07001425 spin_lock(&drvdata->spinlock);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001426 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
Pratik Patel0a10be22012-10-23 21:12:07 -07001427 spin_unlock(&drvdata->spinlock);
Pratik Patela9c0e062012-05-28 13:45:35 -07001428 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001429}
Pratik Patela9c0e062012-05-28 13:45:35 -07001430static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1431 etm_store_ctxid_val);
1432
1433static ssize_t etm_show_ctxid_mask(struct device *dev,
1434 struct device_attribute *attr, char *buf)
1435{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001436 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001437 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001438
Pratik Patela9c0e062012-05-28 13:45:35 -07001439 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1440}
1441
1442static ssize_t etm_store_ctxid_mask(struct device *dev,
1443 struct device_attribute *attr,
1444 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001445{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001446 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001447 unsigned long val;
1448
Pratik Patela9c0e062012-05-28 13:45:35 -07001449 if (sscanf(buf, "%lx", &val) != 1)
1450 return -EINVAL;
1451
Pratik Patel16aefdb2012-05-30 10:41:23 -07001452 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001453 return size;
1454}
1455static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1456 etm_store_ctxid_mask);
1457
1458static ssize_t etm_show_sync_freq(struct device *dev,
1459 struct device_attribute *attr, char *buf)
1460{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001461 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001462 unsigned long val = drvdata->sync_freq;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001463
Pratik Patel6630ebe2012-03-06 16:44:22 -08001464 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1465}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001466
Pratik Patela9c0e062012-05-28 13:45:35 -07001467static ssize_t etm_store_sync_freq(struct device *dev,
1468 struct device_attribute *attr,
1469 const char *buf, size_t size)
1470{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001471 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001472 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001473
Pratik Patela9c0e062012-05-28 13:45:35 -07001474 if (sscanf(buf, "%lx", &val) != 1)
1475 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001476
Pratik Patel16aefdb2012-05-30 10:41:23 -07001477 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001478 return size;
1479}
1480static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1481 etm_store_sync_freq);
1482
1483static ssize_t etm_show_timestamp_event(struct device *dev,
1484 struct device_attribute *attr,
1485 char *buf)
1486{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001487 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001488 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001489
Pratik Patela9c0e062012-05-28 13:45:35 -07001490 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1491}
1492
1493static ssize_t etm_store_timestamp_event(struct device *dev,
1494 struct device_attribute *attr,
1495 const char *buf, size_t size)
1496{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001497 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001498 unsigned long val;
1499
1500 if (sscanf(buf, "%lx", &val) != 1)
1501 return -EINVAL;
1502
Pratik Patel16aefdb2012-05-30 10:41:23 -07001503 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001504 return size;
1505}
1506static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1507 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001508
Pratik Patel938e1ff2012-09-28 23:21:46 -07001509static ssize_t etm_show_pcsave(struct device *dev,
1510 struct device_attribute *attr, char *buf)
1511{
1512 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1513 unsigned long val;
1514
1515 val = drvdata->pcsave_enable;
1516 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1517}
1518
1519static int __etm_store_pcsave(struct etm_drvdata *drvdata, unsigned long val)
1520{
Pratik Patel9dbfa372012-10-23 22:36:40 -07001521 int ret = 0;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001522
1523 ret = clk_prepare_enable(drvdata->clk);
1524 if (ret)
1525 return ret;
1526
Pratik Patel9dbfa372012-10-23 22:36:40 -07001527 get_online_cpus();
Pratik Patel0a10be22012-10-23 21:12:07 -07001528 spin_lock(&drvdata->spinlock);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001529 if (val) {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001530 if (drvdata->pcsave_enable)
1531 goto out;
1532
1533 ret = smp_call_function_single(drvdata->cpu, etm_enable_pcsave,
1534 drvdata, 1);
1535 if (ret)
1536 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001537 drvdata->pcsave_enable = true;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001538
1539 dev_info(drvdata->dev, "PC save enabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001540 } else {
Pratik Patel9dbfa372012-10-23 22:36:40 -07001541 if (!drvdata->pcsave_enable)
1542 goto out;
1543
1544 ret = smp_call_function_single(drvdata->cpu, etm_disable_pcsave,
1545 drvdata, 1);
1546 if (ret)
1547 goto out;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001548 drvdata->pcsave_enable = false;
Pratik Patel9dbfa372012-10-23 22:36:40 -07001549
1550 dev_info(drvdata->dev, "PC save disabled\n");
Pratik Patel938e1ff2012-09-28 23:21:46 -07001551 }
Pratik Patel9dbfa372012-10-23 22:36:40 -07001552out:
Pratik Patel0a10be22012-10-23 21:12:07 -07001553 spin_unlock(&drvdata->spinlock);
Pratik Patel9dbfa372012-10-23 22:36:40 -07001554 put_online_cpus();
Pratik Patel938e1ff2012-09-28 23:21:46 -07001555
1556 clk_disable_unprepare(drvdata->clk);
Pratik Patel9dbfa372012-10-23 22:36:40 -07001557 return ret;
Pratik Patel938e1ff2012-09-28 23:21:46 -07001558}
1559
1560static ssize_t etm_store_pcsave(struct device *dev,
1561 struct device_attribute *attr,
1562 const char *buf, size_t size)
1563{
1564 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1565 unsigned long val;
1566 int ret;
1567
1568 if (sscanf(buf, "%lx", &val) != 1)
1569 return -EINVAL;
1570
1571 ret = __etm_store_pcsave(drvdata, val);
1572 if (ret)
1573 return ret;
1574
1575 return size;
1576}
1577static DEVICE_ATTR(pcsave, S_IRUGO | S_IWUSR, etm_show_pcsave,
1578 etm_store_pcsave);
1579
Pratik Patel6630ebe2012-03-06 16:44:22 -08001580static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001581 &dev_attr_nr_addr_cmp.attr,
1582 &dev_attr_nr_cntr.attr,
1583 &dev_attr_nr_ctxid_cmp.attr,
1584 &dev_attr_reset.attr,
1585 &dev_attr_mode.attr,
1586 &dev_attr_trigger_event.attr,
1587 &dev_attr_enable_event.attr,
1588 &dev_attr_fifofull_level.attr,
1589 &dev_attr_addr_idx.attr,
1590 &dev_attr_addr_single.attr,
1591 &dev_attr_addr_range.attr,
1592 &dev_attr_addr_start.attr,
1593 &dev_attr_addr_stop.attr,
1594 &dev_attr_addr_acctype.attr,
1595 &dev_attr_cntr_idx.attr,
1596 &dev_attr_cntr_rld_val.attr,
1597 &dev_attr_cntr_event.attr,
1598 &dev_attr_cntr_rld_event.attr,
1599 &dev_attr_cntr_val.attr,
1600 &dev_attr_seq_12_event.attr,
1601 &dev_attr_seq_21_event.attr,
1602 &dev_attr_seq_23_event.attr,
1603 &dev_attr_seq_31_event.attr,
1604 &dev_attr_seq_32_event.attr,
1605 &dev_attr_seq_13_event.attr,
1606 &dev_attr_seq_curr_state.attr,
1607 &dev_attr_ctxid_idx.attr,
1608 &dev_attr_ctxid_val.attr,
1609 &dev_attr_ctxid_mask.attr,
1610 &dev_attr_sync_freq.attr,
1611 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001612 NULL,
1613};
1614
1615static struct attribute_group etm_attr_grp = {
1616 .attrs = etm_attrs,
1617};
1618
Pratik Patel3b0ca882012-06-01 16:54:14 -07001619static const struct attribute_group *etm_attr_grps[] = {
1620 &etm_attr_grp,
1621 NULL,
1622};
1623
Pratik Patel97a08f32012-10-22 11:47:41 -07001624static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
1625 void *hcpu)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001626{
Pratik Patel97a08f32012-10-22 11:47:41 -07001627 unsigned int cpu = (unsigned long)hcpu;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001628
Pratik Patel97a08f32012-10-22 11:47:41 -07001629 switch (action & (~CPU_TASKS_FROZEN)) {
1630 case CPU_STARTING:
1631 if (etmdrvdata[cpu] && !etmdrvdata[cpu]->os_unlock) {
1632 spin_lock(&etmdrvdata[cpu]->spinlock);
1633 etm_os_unlock(etmdrvdata[cpu]);
1634 etmdrvdata[cpu]->os_unlock = true;
1635 spin_unlock(&etmdrvdata[cpu]->spinlock);
1636 }
1637
1638 if (etmdrvdata[cpu] && etmdrvdata[cpu]->enable) {
1639 spin_lock(&etmdrvdata[cpu]->spinlock);
1640 __etm_enable(etmdrvdata[cpu]);
1641 spin_unlock(&etmdrvdata[cpu]->spinlock);
1642 }
1643 break;
1644
1645 case CPU_DYING:
1646 if (etmdrvdata[cpu] && etmdrvdata[cpu]->enable) {
1647 spin_lock(&etmdrvdata[cpu]->spinlock);
1648 __etm_disable(etmdrvdata[cpu]);
1649 spin_unlock(&etmdrvdata[cpu]->spinlock);
1650 }
1651 break;
1652 }
1653 return NOTIFY_OK;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001654}
1655
Pratik Patel97a08f32012-10-22 11:47:41 -07001656static struct notifier_block etm_cpu_notifier = {
1657 .notifier_call = etm_cpu_callback,
1658};
1659
Stephen Boyda9510502012-04-24 16:23:34 -07001660static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001661{
Pratik Patel61de7302012-03-07 12:06:10 -08001662 switch (arch) {
1663 case PFT_ARCH_V1_1:
1664 break;
1665 default:
1666 return false;
1667 }
1668 return true;
1669}
1670
Pratik Patele6e41da2012-09-12 12:50:29 -07001671static void __devinit etm_init_arch_data(void *info)
Pratik Patel61de7302012-03-07 12:06:10 -08001672{
Pratik Patel61de7302012-03-07 12:06:10 -08001673 uint32_t etmidr;
1674 uint32_t etmccr;
Pratik Patele6e41da2012-09-12 12:50:29 -07001675 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -07001676
Pratik Patel3b0ca882012-06-01 16:54:14 -07001677 ETM_UNLOCK(drvdata);
Pratik Patel938e1ff2012-09-28 23:21:46 -07001678 /*
1679 * Vote for ETM power/clock enable. ETMPDCR is only accessible via
1680 * memory mapped interface and so use it first to enable power/clock
1681 * to allow subsequent cp14 accesses.
1682 */
Pratik Patelef6da292012-09-17 17:37:19 -07001683 etm_set_pwrup(drvdata);
Pratik Pateld1d65c92012-09-25 23:37:43 -07001684 /*
1685 * Clear power down bit since when this bit is set writes to
1686 * certain registers might be ignored.
1687 */
1688 etm_clr_pwrdwn(drvdata);
Pratik Patelf95c5402012-11-05 18:21:08 -08001689 etm_clr_pwrup(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001690 /* Set prog bit. It will be set from reset but this is included to
1691 * ensure it is set
1692 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001693 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001694
1695 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001696 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001697 drvdata->arch = BMVAL(etmidr, 4, 11);
Pratik Patel7831c082011-06-08 21:44:37 -07001698
Pratik Patel3b0ca882012-06-01 16:54:14 -07001699 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001700 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1701 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1702 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1703 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1704 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001705
Pratik Pateld1d65c92012-09-25 23:37:43 -07001706 etm_set_pwrdwn(drvdata);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001707 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001708}
1709
Pratik Patelc14b4df2012-09-05 18:07:59 -07001710static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1711{
Pratik Patel97a08f32012-10-22 11:47:41 -07001712 drvdata->arch = etmdrvdata[0]->arch;
1713 drvdata->nr_addr_cmp = etmdrvdata[0]->nr_addr_cmp;
1714 drvdata->nr_cntr = etmdrvdata[0]->nr_cntr;
1715 drvdata->nr_ext_inp = etmdrvdata[0]->nr_ext_inp;
1716 drvdata->nr_ext_out = etmdrvdata[0]->nr_ext_out;
1717 drvdata->nr_ctxid_cmp = etmdrvdata[0]->nr_ctxid_cmp;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001718}
1719
Pratik Patel3b0ca882012-06-01 16:54:14 -07001720static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001721{
1722 int i;
1723
1724 drvdata->trigger_event = 0x406F;
1725 drvdata->enable_event = 0x6F;
1726 drvdata->enable_ctrl1 = 0x1;
1727 drvdata->fifofull_level = 0x28;
1728 if (drvdata->nr_addr_cmp >= 2) {
1729 drvdata->addr_val[0] = (uint32_t) _stext;
1730 drvdata->addr_val[1] = (uint32_t) _etext;
1731 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1732 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1733 }
1734 for (i = 0; i < drvdata->nr_cntr; i++) {
1735 drvdata->cntr_event[i] = 0x406F;
1736 drvdata->cntr_rld_event[i] = 0x406F;
1737 }
1738 drvdata->seq_12_event = 0x406F;
1739 drvdata->seq_21_event = 0x406F;
1740 drvdata->seq_23_event = 0x406F;
1741 drvdata->seq_31_event = 0x406F;
1742 drvdata->seq_32_event = 0x406F;
1743 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001744 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1745 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1746 drvdata->sync_freq = 0x100;
1747 else
1748 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001749 drvdata->timestamp_event = 0x406F;
1750
1751 /* Overrides for Krait pass1 */
1752 if (cpu_is_krait_v1()) {
1753 /* Krait pass1 doesn't support include filtering and non-cycle
1754 * accurate tracing
1755 */
1756 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1757 drvdata->ctrl = 0x1000;
1758 drvdata->enable_ctrl1 = 0x1000000;
1759 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1760 drvdata->addr_val[i] = 0x0;
1761 drvdata->addr_acctype[i] = 0x0;
1762 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1763 }
1764 }
1765}
1766
Pratik Patel492b3012012-03-06 14:22:30 -08001767static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001768{
Pratik Patele5771792011-09-17 18:33:54 -07001769 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001770 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001771 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001772 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001773 struct resource *res;
Pratik Patel26477792012-09-07 01:35:36 -07001774 uint32_t reg_size;
1775 static int count;
1776 void *baddr;
1777 struct msm_client_dump dump;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001778 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001779
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001780 if (pdev->dev.of_node) {
1781 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1782 if (IS_ERR(pdata))
1783 return PTR_ERR(pdata);
1784 pdev->dev.platform_data = pdata;
1785 }
1786
Pratik Patel4a1b2522012-06-17 15:31:15 -07001787 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1788 if (!drvdata)
1789 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001790 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001791 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001792
Pratik Patel4a1b2522012-06-17 15:31:15 -07001793 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1794 if (!res)
1795 return -ENODEV;
Pratik Patel26477792012-09-07 01:35:36 -07001796 reg_size = resource_size(res);
Pratik Patel2c09b762012-07-21 15:54:54 -07001797
Pratik Patel4a1b2522012-06-17 15:31:15 -07001798 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1799 if (!drvdata->base)
1800 return -ENOMEM;
1801
Pratik Patel0a10be22012-10-23 21:12:07 -07001802 spin_lock_init(&drvdata->spinlock);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001803 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07001804
Pratik Patel4a1b2522012-06-17 15:31:15 -07001805 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001806 if (IS_ERR(drvdata->clk)) {
1807 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001808 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001809 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001810
Pratik Patel6fb38342012-06-03 14:51:38 -07001811 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001812 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001813 goto err0;
1814
Pratik Patel16aefdb2012-05-30 10:41:23 -07001815 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001816 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001817 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001818
Pratik Patel97a08f32012-10-22 11:47:41 -07001819 drvdata->cpu = count++;
1820
1821 get_online_cpus();
1822 etmdrvdata[drvdata->cpu] = drvdata;
1823
1824 if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, NULL, 1))
1825 drvdata->os_unlock = true;
1826 /*
1827 * Use CPU0 to populate read-only configuration data for ETM0. For
1828 * other ETMs copy it over from ETM0.
Pratik Patelc14b4df2012-09-05 18:07:59 -07001829 */
1830 if (drvdata->cpu == 0) {
Pratik Patel97a08f32012-10-22 11:47:41 -07001831 register_hotcpu_notifier(&etm_cpu_notifier);
1832 if (smp_call_function_single(drvdata->cpu, etm_init_arch_data,
1833 drvdata, 1))
1834 dev_err(dev, "ETM arch init failed\n");
Pratik Patelc14b4df2012-09-05 18:07:59 -07001835 } else {
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001836 etm_copy_arch_data(drvdata);
1837 }
Pratik Patel97a08f32012-10-22 11:47:41 -07001838
1839 put_online_cpus();
1840
Pratik Pateldc3a0a42012-09-11 17:48:23 -07001841 if (etm_arch_supported(drvdata->arch) == false) {
1842 ret = -EINVAL;
1843 goto err1;
Pratik Patelc14b4df2012-09-05 18:07:59 -07001844 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001845 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001846
Pratik Patel16aefdb2012-05-30 10:41:23 -07001847 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001848
Pratik Patel26477792012-09-07 01:35:36 -07001849 baddr = devm_kzalloc(dev, PAGE_SIZE + reg_size, GFP_KERNEL);
1850 if (baddr) {
1851 *(uint32_t *)(baddr + ETM_REG_DUMP_VER_OFF) = ETM_REG_DUMP_VER;
1852 dump.id = MSM_ETM0_REG + drvdata->cpu;
1853 dump.start_addr = virt_to_phys(baddr);
1854 dump.end_addr = dump.start_addr + PAGE_SIZE + reg_size;
1855 ret = msm_dump_table_register(&dump);
1856 if (ret) {
1857 devm_kfree(dev, baddr);
Pratik Patel97a08f32012-10-22 11:47:41 -07001858 dev_err(dev, "ETM REG dump setup failed/unsupported\n");
Pratik Patel26477792012-09-07 01:35:36 -07001859 }
1860 } else {
1861 dev_err(dev, "ETM REG dump space allocation failed\n");
1862 }
1863
Pratik Patel4a1b2522012-06-17 15:31:15 -07001864 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001865 if (!desc) {
1866 ret = -ENOMEM;
Pratik Patel97a08f32012-10-22 11:47:41 -07001867 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001868 }
1869 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1870 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1871 desc->ops = &etm_cs_ops;
1872 desc->pdata = pdev->dev.platform_data;
1873 desc->dev = &pdev->dev;
1874 desc->groups = etm_attr_grps;
1875 desc->owner = THIS_MODULE;
1876 drvdata->csdev = coresight_register(desc);
1877 if (IS_ERR(drvdata->csdev)) {
1878 ret = PTR_ERR(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07001879 goto err2;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001880 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001881
Pratik Patel938e1ff2012-09-28 23:21:46 -07001882 if (pdev->dev.of_node)
1883 drvdata->pcsave_impl = of_property_read_bool(pdev->dev.of_node,
1884 "qcom,pc-save");
1885 if (drvdata->pcsave_impl) {
1886 ret = device_create_file(&drvdata->csdev->dev,
1887 &dev_attr_pcsave);
1888 if (ret)
1889 dev_err(dev, "ETM pcsave dev node creation failed\n");
1890 }
1891
Pratik Patel4a1b2522012-06-17 15:31:15 -07001892 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001893
Pratik Patel3b0ca882012-06-01 16:54:14 -07001894 if (boot_enable)
1895 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001896
Pratik Patel938e1ff2012-09-28 23:21:46 -07001897 if (drvdata->pcsave_impl && boot_pcsave_enable)
1898 __etm_store_pcsave(drvdata, true);
1899
Pratik Patel7831c082011-06-08 21:44:37 -07001900 return 0;
Pratik Patel97a08f32012-10-22 11:47:41 -07001901err2:
1902 if (drvdata->cpu == 0)
1903 unregister_hotcpu_notifier(&etm_cpu_notifier);
1904 wake_lock_destroy(&drvdata->wake_lock);
1905 return ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001906err1:
Pratik Patel97a08f32012-10-22 11:47:41 -07001907 if (drvdata->cpu == 0)
1908 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001909 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001910err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001911 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07001912 return ret;
1913}
1914
Pratik Patelf6fe9182012-03-20 14:04:18 -07001915static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001916{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001917 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1918
Pratik Patel938e1ff2012-09-28 23:21:46 -07001919 device_remove_file(&drvdata->csdev->dev, &dev_attr_pcsave);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001920 coresight_unregister(drvdata->csdev);
Pratik Patel97a08f32012-10-22 11:47:41 -07001921 if (drvdata->cpu == 0)
1922 unregister_hotcpu_notifier(&etm_cpu_notifier);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001923 wake_lock_destroy(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -07001924 return 0;
1925}
1926
Pratik Patel9eae4822012-05-14 17:34:53 -07001927static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001928 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001929 {}
1930};
1931
Pratik Patel492b3012012-03-06 14:22:30 -08001932static struct platform_driver etm_driver = {
1933 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001934 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001935 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001936 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001937 .owner = THIS_MODULE,
1938 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001939 },
1940};
1941
Pratik Patel492b3012012-03-06 14:22:30 -08001942int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001943{
Pratik Patel492b3012012-03-06 14:22:30 -08001944 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001945}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001946module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001947
Pratik Patelf6fe9182012-03-20 14:04:18 -07001948void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001949{
Pratik Patel492b3012012-03-06 14:22:30 -08001950 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001951}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001952module_exit(etm_exit);
1953
1954MODULE_LICENSE("GPL v2");
1955MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");