blob: 877b189d9cf78af2fe79848b2987e1f8c79e2b2b [file] [log] [blame]
Pratik Patel17f3b822011-11-21 12:41:47 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. 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>
Steve Mucklef132c6c2012-06-06 18:30:57 -070026#include <linux/pm_qos.h>
Pratik Patel6630ebe2012-03-06 16:44:22 -080027#include <linux/sysfs.h>
28#include <linux/stat.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070029#include <linux/clk.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070030#include <linux/coresight.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080031#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080032#include <mach/socinfo.h>
Pratik Patel7831c082011-06-08 21:44:37 -070033
Pratik Patel1746b8f2012-06-02 21:11:41 -070034#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070035
Pratik Patel16aefdb2012-05-30 10:41:23 -070036#define etm_writel(drvdata, cpu, val, off) \
37 __raw_writel((val), drvdata->base + (SZ_4K * cpu) + off)
38#define etm_readl(drvdata, cpu, off) \
39 __raw_readl(drvdata->base + (SZ_4K * cpu) + off)
Pratik Patel7831c082011-06-08 21:44:37 -070040
41/*
42 * Device registers:
43 * 0x000 - 0x2FC: Trace registers
44 * 0x300 - 0x314: Management registers
45 * 0x318 - 0xEFC: Trace registers
46 *
47 * Coresight registers
48 * 0xF00 - 0xF9C: Management registers
49 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
50 * Trace registers in PFTv1.1
51 * 0xFA8 - 0xFFC: Management registers
52 */
53
54/* Trace registers (0x000-0x2FC) */
55#define ETMCR (0x000)
56#define ETMCCR (0x004)
57#define ETMTRIGGER (0x008)
58#define ETMSR (0x010)
59#define ETMSCR (0x014)
60#define ETMTSSCR (0x018)
61#define ETMTEEVR (0x020)
62#define ETMTECR1 (0x024)
63#define ETMFFLR (0x02C)
64#define ETMACVRn(n) (0x040 + (n * 4))
65#define ETMACTRn(n) (0x080 + (n * 4))
66#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
67#define ETMCNTENRn(n) (0x150 + (n * 4))
68#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
69#define ETMCNTVRn(n) (0x170 + (n * 4))
70#define ETMSQ12EVR (0x180)
71#define ETMSQ21EVR (0x184)
72#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -080073#define ETMSQ31EVR (0x18C)
74#define ETMSQ32EVR (0x190)
75#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -070076#define ETMSQR (0x19C)
77#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
78#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
79#define ETMCIDCMR (0x1BC)
80#define ETMIMPSPEC0 (0x1C0)
81#define ETMIMPSPEC1 (0x1C4)
82#define ETMIMPSPEC2 (0x1C8)
83#define ETMIMPSPEC3 (0x1CC)
84#define ETMIMPSPEC4 (0x1D0)
85#define ETMIMPSPEC5 (0x1D4)
86#define ETMIMPSPEC6 (0x1D8)
87#define ETMIMPSPEC7 (0x1DC)
88#define ETMSYNCFR (0x1E0)
89#define ETMIDR (0x1E4)
90#define ETMCCER (0x1E8)
91#define ETMEXTINSELR (0x1EC)
92#define ETMTESSEICR (0x1F0)
93#define ETMEIBCR (0x1F4)
94#define ETMTSEVR (0x1F8)
95#define ETMAUXCR (0x1FC)
96#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -080097#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -070098/* Management registers (0x300-0x314) */
99#define ETMOSLAR (0x300)
100#define ETMOSLSR (0x304)
101#define ETMOSSRR (0x308)
102#define ETMPDCR (0x310)
103#define ETMPDSR (0x314)
104
Pratik Patel61de7302012-03-07 12:06:10 -0800105#define ETM_MAX_ADDR_CMP (16)
106#define ETM_MAX_CNTR (4)
107#define ETM_MAX_CTXID_CMP (3)
108
Pratik Patel6630ebe2012-03-06 16:44:22 -0800109#define ETM_MODE_EXCLUDE BIT(0)
110#define ETM_MODE_CYCACC BIT(1)
111#define ETM_MODE_STALL BIT(2)
112#define ETM_MODE_TIMESTAMP BIT(3)
113#define ETM_MODE_CTXID BIT(4)
114#define ETM_MODE_ALL (0x1F)
115
116#define ETM_EVENT_MASK (0x1FFFF)
117#define ETM_SYNC_MASK (0xFFF)
118#define ETM_ALL_MASK (0xFFFFFFFF)
119
120#define ETM_SEQ_STATE_MAX_VAL (0x2)
121
122enum {
123 ETM_ADDR_TYPE_NONE,
124 ETM_ADDR_TYPE_SINGLE,
125 ETM_ADDR_TYPE_RANGE,
126 ETM_ADDR_TYPE_START,
127 ETM_ADDR_TYPE_STOP,
128};
129
Pratik Patel492b3012012-03-06 14:22:30 -0800130#define ETM_LOCK(cpu) \
Pratik Patel7831c082011-06-08 21:44:37 -0700131do { \
132 mb(); \
Pratik Patel16aefdb2012-05-30 10:41:23 -0700133 etm_writel(drvdata, cpu, 0x0, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -0700134} while (0)
Pratik Patel492b3012012-03-06 14:22:30 -0800135#define ETM_UNLOCK(cpu) \
Pratik Patel7831c082011-06-08 21:44:37 -0700136do { \
Pratik Patel16aefdb2012-05-30 10:41:23 -0700137 etm_writel(drvdata, cpu, CS_UNLOCK_MAGIC, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -0700138 mb(); \
139} while (0)
140
Pratik Patel7831c082011-06-08 21:44:37 -0700141
Pratik Patel6630ebe2012-03-06 16:44:22 -0800142#ifdef MODULE_PARAM_PREFIX
143#undef MODULE_PARAM_PREFIX
144#endif
Pratik Patel1746b8f2012-06-02 21:11:41 -0700145#define MODULE_PARAM_PREFIX "coresight."
Pratik Patel6630ebe2012-03-06 16:44:22 -0800146
Pratik Patel29cba152012-01-03 11:40:26 -0800147#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel61de7302012-03-07 12:06:10 -0800148static int etm_boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800149#else
Pratik Patel61de7302012-03-07 12:06:10 -0800150static int etm_boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800151#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700152module_param_named(
Pratik Patel61de7302012-03-07 12:06:10 -0800153 etm_boot_enable, etm_boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700154);
155
Pratik Patel16aefdb2012-05-30 10:41:23 -0700156struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700157 void __iomem *base;
Pratik Patel61de7302012-03-07 12:06:10 -0800158 bool enabled;
Pratik Patel7831c082011-06-08 21:44:37 -0700159 struct wake_lock wake_lock;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700160 struct pm_qos_request qos_req;
Pratik Patele10a77c2012-03-20 10:35:16 -0700161 struct qdss_source *src;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800162 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700163 struct device *dev;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800164 struct kobject *kobj;
Pratik Patelf17b1472012-05-25 22:23:52 -0700165 struct clk *clk;
Pratik Patel61de7302012-03-07 12:06:10 -0800166 uint8_t arch;
167 uint8_t nr_addr_cmp;
168 uint8_t nr_cntr;
169 uint8_t nr_ext_inp;
170 uint8_t nr_ext_out;
171 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800172 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800173 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800174 uint32_t ctrl;
175 uint32_t trigger_event;
176 uint32_t startstop_ctrl;
177 uint32_t enable_event;
178 uint32_t enable_ctrl1;
179 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800180 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800181 uint32_t addr_val[ETM_MAX_ADDR_CMP];
182 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800183 uint32_t addr_type[ETM_MAX_ADDR_CMP];
184 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800185 uint32_t cntr_rld_val[ETM_MAX_CNTR];
186 uint32_t cntr_event[ETM_MAX_CNTR];
187 uint32_t cntr_rld_event[ETM_MAX_CNTR];
188 uint32_t cntr_val[ETM_MAX_CNTR];
189 uint32_t seq_12_event;
190 uint32_t seq_21_event;
191 uint32_t seq_23_event;
192 uint32_t seq_31_event;
193 uint32_t seq_32_event;
194 uint32_t seq_13_event;
195 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800196 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800197 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
198 uint32_t ctxid_mask;
199 uint32_t sync_freq;
200 uint32_t timestamp_event;
Pratik Patel7831c082011-06-08 21:44:37 -0700201};
202
Pratik Patel16aefdb2012-05-30 10:41:23 -0700203static struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -0700204
Pratik Patel7831c082011-06-08 21:44:37 -0700205
Pratik Patel17f3b822011-11-21 12:41:47 -0800206/* ETM clock is derived from the processor clock and gets enabled on a
207 * logical OR of below items on Krait (pass2 onwards):
208 * 1.CPMR[ETMCLKEN] is 1
209 * 2.ETMCR[PD] is 0
210 * 3.ETMPDCR[PU] is 1
211 * 4.Reset is asserted (core or debug)
212 * 5.APB memory mapped requests (eg. EDAP access)
213 *
214 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
215 * enables
216 *
217 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
218 * clock vote in the driver and the save-restore code uses 1. above
219 * for its vote
220 */
Pratik Patel61de7302012-03-07 12:06:10 -0800221static void etm_set_pwrdwn(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700222{
223 uint32_t etmcr;
224
Pratik Patel16aefdb2012-05-30 10:41:23 -0700225 etmcr = etm_readl(drvdata, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700226 etmcr |= BIT(0);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700227 etm_writel(drvdata, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700228}
229
Pratik Patel61de7302012-03-07 12:06:10 -0800230static void etm_clr_pwrdwn(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700231{
232 uint32_t etmcr;
233
Pratik Patel16aefdb2012-05-30 10:41:23 -0700234 etmcr = etm_readl(drvdata, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700235 etmcr &= ~BIT(0);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700236 etm_writel(drvdata, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700237}
238
Pratik Patel492b3012012-03-06 14:22:30 -0800239static void etm_set_prog(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700240{
241 uint32_t etmcr;
242 int count;
243
Pratik Patel16aefdb2012-05-30 10:41:23 -0700244 etmcr = etm_readl(drvdata, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700245 etmcr |= BIT(10);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700246 etm_writel(drvdata, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700247
Pratik Patel16aefdb2012-05-30 10:41:23 -0700248 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700249 && count > 0; count--)
250 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800251 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel16aefdb2012-05-30 10:41:23 -0700252 etm_readl(drvdata, cpu, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700253}
254
Pratik Patel61de7302012-03-07 12:06:10 -0800255static void etm_clr_prog(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700256{
257 uint32_t etmcr;
258 int count;
259
Pratik Patel16aefdb2012-05-30 10:41:23 -0700260 etmcr = etm_readl(drvdata, cpu, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700261 etmcr &= ~BIT(10);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700262 etm_writel(drvdata, cpu, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700263
Pratik Patel16aefdb2012-05-30 10:41:23 -0700264 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700265 && count > 0; count--)
266 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800267 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel16aefdb2012-05-30 10:41:23 -0700268 etm_readl(drvdata, cpu, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700269}
270
Pratik Patel61de7302012-03-07 12:06:10 -0800271static void __etm_enable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700272{
Pratik Patel17f3b822011-11-21 12:41:47 -0800273 int i;
Pratik Patel7831c082011-06-08 21:44:37 -0700274
Pratik Patel492b3012012-03-06 14:22:30 -0800275 ETM_UNLOCK(cpu);
Pratik Patel17f3b822011-11-21 12:41:47 -0800276 /* Vote for ETM power/clock enable */
Pratik Patel61de7302012-03-07 12:06:10 -0800277 etm_clr_pwrdwn(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -0800278 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700279
Pratik Patel16aefdb2012-05-30 10:41:23 -0700280 etm_writel(drvdata, cpu, drvdata->ctrl | BIT(10), ETMCR);
281 etm_writel(drvdata, cpu, drvdata->trigger_event, ETMTRIGGER);
282 etm_writel(drvdata, cpu, drvdata->startstop_ctrl, ETMTSSCR);
283 etm_writel(drvdata, cpu, drvdata->enable_event, ETMTEEVR);
284 etm_writel(drvdata, cpu, drvdata->enable_ctrl1, ETMTECR1);
285 etm_writel(drvdata, cpu, drvdata->fifofull_level, ETMFFLR);
286 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
287 etm_writel(drvdata, cpu, drvdata->addr_val[i], ETMACVRn(i));
288 etm_writel(drvdata, cpu, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700289 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700290 for (i = 0; i < drvdata->nr_cntr; i++) {
291 etm_writel(drvdata, cpu, drvdata->cntr_rld_val[i],
292 ETMCNTRLDVRn(i));
293 etm_writel(drvdata, cpu, drvdata->cntr_event[i], ETMCNTENRn(i));
294 etm_writel(drvdata, cpu, drvdata->cntr_rld_event[i],
295 ETMCNTRLDEVRn(i));
296 etm_writel(drvdata, cpu, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800297 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700298 etm_writel(drvdata, cpu, drvdata->seq_12_event, ETMSQ12EVR);
299 etm_writel(drvdata, cpu, drvdata->seq_21_event, ETMSQ21EVR);
300 etm_writel(drvdata, cpu, drvdata->seq_23_event, ETMSQ23EVR);
301 etm_writel(drvdata, cpu, drvdata->seq_31_event, ETMSQ31EVR);
302 etm_writel(drvdata, cpu, drvdata->seq_32_event, ETMSQ32EVR);
303 etm_writel(drvdata, cpu, drvdata->seq_13_event, ETMSQ13EVR);
304 etm_writel(drvdata, cpu, drvdata->seq_curr_state, ETMSQR);
305 for (i = 0; i < drvdata->nr_ext_out; i++)
306 etm_writel(drvdata, cpu, 0x0000406F, ETMEXTOUTEVRn(i));
307 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
308 etm_writel(drvdata, cpu, drvdata->ctxid_val[i], ETMCIDCVRn(i));
309 etm_writel(drvdata, cpu, drvdata->ctxid_mask, ETMCIDCMR);
310 etm_writel(drvdata, cpu, drvdata->sync_freq, ETMSYNCFR);
311 etm_writel(drvdata, cpu, 0x00000000, ETMEXTINSELR);
312 etm_writel(drvdata, cpu, drvdata->timestamp_event, ETMTSEVR);
313 etm_writel(drvdata, cpu, 0x00000000, ETMAUXCR);
314 etm_writel(drvdata, cpu, cpu+1, ETMTRACEIDR);
315 etm_writel(drvdata, cpu, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800316
Pratik Patel61de7302012-03-07 12:06:10 -0800317 etm_clr_prog(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -0800318 ETM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700319}
320
Pratik Patel61de7302012-03-07 12:06:10 -0800321static int etm_enable(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700322{
Pratik Patel17f3b822011-11-21 12:41:47 -0800323 int ret, cpu;
Pratik Patel7831c082011-06-08 21:44:37 -0700324
Pratik Patel16aefdb2012-05-30 10:41:23 -0700325 if (drvdata->enabled) {
326 dev_err(drvdata->dev, "ETM tracing already enabled\n");
Pratik Patel61de7302012-03-07 12:06:10 -0800327 ret = -EPERM;
328 goto err;
329 }
330
Pratik Patel16aefdb2012-05-30 10:41:23 -0700331 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700332 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700333 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700334 *
335 * we rely on the user to prevent hotplug on/off racing with this
336 * operation and to ensure cores where trace is expected to be turned
337 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700338 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700339 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700340
Pratik Patel16aefdb2012-05-30 10:41:23 -0700341 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700342 if (ret)
343 goto err_clk;
344
Pratik Patel16aefdb2012-05-30 10:41:23 -0700345 ret = qdss_enable(drvdata->src);
Pratik Patele10a77c2012-03-20 10:35:16 -0700346 if (ret)
347 goto err_qdss;
348
Pratik Patel17f3b822011-11-21 12:41:47 -0800349 for_each_online_cpu(cpu)
Pratik Patel61de7302012-03-07 12:06:10 -0800350 __etm_enable(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700351
Pratik Patel16aefdb2012-05-30 10:41:23 -0700352 drvdata->enabled = true;
Pratik Patel7831c082011-06-08 21:44:37 -0700353
Pratik Patel16aefdb2012-05-30 10:41:23 -0700354 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
355 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700356
Pratik Patel16aefdb2012-05-30 10:41:23 -0700357 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700358 return 0;
Pratik Patele10a77c2012-03-20 10:35:16 -0700359
360err_qdss:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700361 clk_disable_unprepare(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700362err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700363 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
364 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800365err:
366 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700367}
368
Pratik Patel61de7302012-03-07 12:06:10 -0800369static void __etm_disable(int cpu)
Pratik Patel7831c082011-06-08 21:44:37 -0700370{
Pratik Patel492b3012012-03-06 14:22:30 -0800371 ETM_UNLOCK(cpu);
372 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700373
Pratik Patel17f3b822011-11-21 12:41:47 -0800374 /* program trace enable to low by using always false event */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700375 etm_writel(drvdata, cpu, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700376
Pratik Patel17f3b822011-11-21 12:41:47 -0800377 /* Vote for ETM power/clock disable */
Pratik Patel61de7302012-03-07 12:06:10 -0800378 etm_set_pwrdwn(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -0800379 ETM_LOCK(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700380}
381
Pratik Patel61de7302012-03-07 12:06:10 -0800382static int etm_disable(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700383{
Pratik Patel61de7302012-03-07 12:06:10 -0800384 int ret, cpu;
385
Pratik Patel16aefdb2012-05-30 10:41:23 -0700386 if (!drvdata->enabled) {
387 dev_err(drvdata->dev, "ETM tracing already disabled\n");
Pratik Patel61de7302012-03-07 12:06:10 -0800388 ret = -EPERM;
389 goto err;
390 }
Pratik Patel17f3b822011-11-21 12:41:47 -0800391
Pratik Patel16aefdb2012-05-30 10:41:23 -0700392 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700393 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700394 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700395 *
396 * we rely on the user to prevent hotplug on/off racing with this
397 * operation and to ensure cores where trace is expected to be turned
398 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700399 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700400 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700401
Pratik Patel17f3b822011-11-21 12:41:47 -0800402 for_each_online_cpu(cpu)
Pratik Patel61de7302012-03-07 12:06:10 -0800403 __etm_disable(cpu);
Pratik Patele10a77c2012-03-20 10:35:16 -0700404
Pratik Patel16aefdb2012-05-30 10:41:23 -0700405 drvdata->enabled = false;
Pratik Patelf17b1472012-05-25 22:23:52 -0700406
Pratik Patel16aefdb2012-05-30 10:41:23 -0700407 qdss_disable(drvdata->src);
Pratik Patel7831c082011-06-08 21:44:37 -0700408
Pratik Patel16aefdb2012-05-30 10:41:23 -0700409 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700410
Pratik Patel16aefdb2012-05-30 10:41:23 -0700411 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
412 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700413
Pratik Patel16aefdb2012-05-30 10:41:23 -0700414 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel61de7302012-03-07 12:06:10 -0800415 return 0;
416err:
417 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700418}
419
Pratik Patel17f3b822011-11-21 12:41:47 -0800420/* Memory mapped writes to clear os lock not supported */
Pratik Patel492b3012012-03-06 14:22:30 -0800421static void etm_os_unlock(void *unused)
Pratik Patel17f3b822011-11-21 12:41:47 -0800422{
423 unsigned long value = 0x0;
424
425 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
426 asm("isb\n\t");
427}
428
Pratik Patela9c0e062012-05-28 13:45:35 -0700429static ssize_t etm_show_enabled(struct device *dev,
430 struct device_attribute *attr, char *buf)
431{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700432 unsigned long val = drvdata->enabled;
Pratik Patela9c0e062012-05-28 13:45:35 -0700433 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800434}
435
Pratik Patela9c0e062012-05-28 13:45:35 -0700436static ssize_t etm_store_enabled(struct device *dev,
437 struct device_attribute *attr,
438 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800439{
440 int ret = 0;
441 unsigned long val;
442
443 if (sscanf(buf, "%lx", &val) != 1)
444 return -EINVAL;
445
Pratik Patel16aefdb2012-05-30 10:41:23 -0700446 mutex_lock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800447 if (val)
448 ret = etm_enable();
449 else
450 ret = etm_disable();
Pratik Patel16aefdb2012-05-30 10:41:23 -0700451 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800452
453 if (ret)
454 return ret;
Pratik Patela9c0e062012-05-28 13:45:35 -0700455 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800456}
Pratik Patela9c0e062012-05-28 13:45:35 -0700457static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, etm_show_enabled,
458 etm_store_enabled);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800459
Pratik Patela9c0e062012-05-28 13:45:35 -0700460static ssize_t etm_show_nr_addr_cmp(struct device *dev,
461 struct device_attribute *attr, char *buf)
462{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700463 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patela9c0e062012-05-28 13:45:35 -0700464 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
465}
466static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
467
468static ssize_t etm_show_nr_cntr(struct device *dev,
469 struct device_attribute *attr, char *buf)
470{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700471 unsigned long val = drvdata->nr_cntr;
Pratik Patela9c0e062012-05-28 13:45:35 -0700472 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
473}
474static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
475
476static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
477 struct device_attribute *attr, char *buf)
478{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700479 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patela9c0e062012-05-28 13:45:35 -0700480 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
481}
482static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
483
484static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
485 char *buf)
486{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700487 unsigned long val = drvdata->reset;
Pratik Patela9c0e062012-05-28 13:45:35 -0700488 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
489}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800490
Pratik Pateld30deda2012-02-01 14:40:55 -0800491/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700492static ssize_t etm_store_reset(struct device *dev,
493 struct device_attribute *attr, const char *buf,
494 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800495{
496 int i;
497 unsigned long val;
498
499 if (sscanf(buf, "%lx", &val) != 1)
500 return -EINVAL;
501
Pratik Patel16aefdb2012-05-30 10:41:23 -0700502 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800503 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700504 drvdata->mode = ETM_MODE_EXCLUDE;
505 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800506 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700507 drvdata->mode |= ETM_MODE_CYCACC;
508 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800509 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700510 drvdata->trigger_event = 0x406F;
511 drvdata->startstop_ctrl = 0x0;
512 drvdata->enable_event = 0x6F;
513 drvdata->enable_ctrl1 = 0x1000000;
514 drvdata->fifofull_level = 0x28;
515 drvdata->addr_idx = 0x0;
516 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
517 drvdata->addr_val[i] = 0x0;
518 drvdata->addr_acctype[i] = 0x0;
519 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800520 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700521 drvdata->cntr_idx = 0x0;
522 for (i = 0; i < drvdata->nr_cntr; i++) {
523 drvdata->cntr_rld_val[i] = 0x0;
524 drvdata->cntr_event[i] = 0x406F;
525 drvdata->cntr_rld_event[i] = 0x406F;
526 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800527 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700528 drvdata->seq_12_event = 0x406F;
529 drvdata->seq_21_event = 0x406F;
530 drvdata->seq_23_event = 0x406F;
531 drvdata->seq_31_event = 0x406F;
532 drvdata->seq_32_event = 0x406F;
533 drvdata->seq_13_event = 0x406F;
534 drvdata->seq_curr_state = 0x0;
535 drvdata->ctxid_idx = 0x0;
536 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
537 drvdata->ctxid_val[i] = 0x0;
538 drvdata->ctxid_mask = 0x0;
539 drvdata->sync_freq = 0x80;
540 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800541 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700542 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700543 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800544}
Pratik Patela9c0e062012-05-28 13:45:35 -0700545static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800546
Pratik Patela9c0e062012-05-28 13:45:35 -0700547static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
548 char *buf)
549{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700550 unsigned long val = drvdata->mode;
Pratik Patela9c0e062012-05-28 13:45:35 -0700551 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
552}
553
554static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
555 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800556{
557 unsigned long val;
558
559 if (sscanf(buf, "%lx", &val) != 1)
560 return -EINVAL;
561
Pratik Patel16aefdb2012-05-30 10:41:23 -0700562 mutex_lock(&drvdata->mutex);
563 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800564
Pratik Patel16aefdb2012-05-30 10:41:23 -0700565 if (drvdata->mode & ETM_MODE_EXCLUDE)
566 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800567 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700568 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800569
Pratik Patel16aefdb2012-05-30 10:41:23 -0700570 if (drvdata->mode & ETM_MODE_CYCACC)
571 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800572 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700573 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800574
Pratik Patel16aefdb2012-05-30 10:41:23 -0700575 if (drvdata->mode & ETM_MODE_STALL)
576 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800577 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700578 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800579
Pratik Patel16aefdb2012-05-30 10:41:23 -0700580 if (drvdata->mode & ETM_MODE_TIMESTAMP)
581 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800582 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700583 drvdata->ctrl &= ~BIT(28);
584 if (drvdata->mode & ETM_MODE_CTXID)
585 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800586 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700587 drvdata->ctrl &= ~(BIT(14) | BIT(15));
588 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800589
Pratik Patela9c0e062012-05-28 13:45:35 -0700590 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800591}
Pratik Patela9c0e062012-05-28 13:45:35 -0700592static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800593
Pratik Patela9c0e062012-05-28 13:45:35 -0700594static ssize_t etm_show_trigger_event(struct device *dev,
595 struct device_attribute *attr, char *buf)
596{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700597 unsigned long val = drvdata->trigger_event;
Pratik Patela9c0e062012-05-28 13:45:35 -0700598 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
599}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800600
Pratik Patela9c0e062012-05-28 13:45:35 -0700601static ssize_t etm_store_trigger_event(struct device *dev,
602 struct device_attribute *attr,
603 const char *buf, size_t size)
604{
605 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800606
Pratik Patela9c0e062012-05-28 13:45:35 -0700607 if (sscanf(buf, "%lx", &val) != 1)
608 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800609
Pratik Patel16aefdb2012-05-30 10:41:23 -0700610 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700611 return size;
612}
613static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
614 etm_store_trigger_event);
615
616static ssize_t etm_show_enable_event(struct device *dev,
617 struct device_attribute *attr, char *buf)
618{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700619 unsigned long val = drvdata->enable_event;
Pratik Patela9c0e062012-05-28 13:45:35 -0700620 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
621}
622
623static ssize_t etm_store_enable_event(struct device *dev,
624 struct device_attribute *attr,
625 const char *buf, size_t size)
626{
627 unsigned long val;
628
629 if (sscanf(buf, "%lx", &val) != 1)
630 return -EINVAL;
631
Pratik Patel16aefdb2012-05-30 10:41:23 -0700632 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700633 return size;
634}
635static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
636 etm_store_enable_event);
637
638static ssize_t etm_show_fifofull_level(struct device *dev,
639 struct device_attribute *attr, char *buf)
640{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700641 unsigned long val = drvdata->fifofull_level;
Pratik Patela9c0e062012-05-28 13:45:35 -0700642 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
643}
644
645static ssize_t etm_store_fifofull_level(struct device *dev,
646 struct device_attribute *attr,
647 const char *buf, size_t size)
648{
649 unsigned long val;
650
651 if (sscanf(buf, "%lx", &val) != 1)
652 return -EINVAL;
653
Pratik Patel16aefdb2012-05-30 10:41:23 -0700654 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700655 return size;
656}
657static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
658 etm_store_fifofull_level);
659
660static ssize_t etm_show_addr_idx(struct device *dev,
661 struct device_attribute *attr, char *buf)
662{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700663 unsigned long val = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700664 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
665}
666
667static ssize_t etm_store_addr_idx(struct device *dev,
668 struct device_attribute *attr,
669 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800670{
671 unsigned long val;
672
673 if (sscanf(buf, "%lx", &val) != 1)
674 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700675 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800676 return -EINVAL;
677
678 /* Use mutex to ensure index doesn't change while it gets dereferenced
679 * multiple times within a mutex block elsewhere.
680 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700681 mutex_lock(&drvdata->mutex);
682 drvdata->addr_idx = val;
683 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700684 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800685}
Pratik Patela9c0e062012-05-28 13:45:35 -0700686static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
687 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800688
Pratik Patela9c0e062012-05-28 13:45:35 -0700689static ssize_t etm_show_addr_single(struct device *dev,
690 struct device_attribute *attr, char *buf)
691{
692 unsigned long val;
693 uint8_t idx;
694
Pratik Patel16aefdb2012-05-30 10:41:23 -0700695 mutex_lock(&drvdata->mutex);
696 idx = drvdata->addr_idx;
697 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
698 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
699 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700700 return -EPERM;
701 }
702
Pratik Patel16aefdb2012-05-30 10:41:23 -0700703 val = drvdata->addr_val[idx];
704 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700705 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
706}
707
708static ssize_t etm_store_addr_single(struct device *dev,
709 struct device_attribute *attr,
710 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800711{
712 unsigned long val;
713 uint8_t idx;
714
715 if (sscanf(buf, "%lx", &val) != 1)
716 return -EINVAL;
717
Pratik Patel16aefdb2012-05-30 10:41:23 -0700718 mutex_lock(&drvdata->mutex);
719 idx = drvdata->addr_idx;
720 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
721 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
722 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800723 return -EPERM;
724 }
725
Pratik Patel16aefdb2012-05-30 10:41:23 -0700726 drvdata->addr_val[idx] = val;
727 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
728 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700729 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800730}
Pratik Patela9c0e062012-05-28 13:45:35 -0700731static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
732 etm_store_addr_single);
733
734static ssize_t etm_show_addr_range(struct device *dev,
735 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800736{
Pratik Patela9c0e062012-05-28 13:45:35 -0700737 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800738 uint8_t idx;
739
Pratik Patel16aefdb2012-05-30 10:41:23 -0700740 mutex_lock(&drvdata->mutex);
741 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700742 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700743 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700744 return -EPERM;
745 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700746 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
747 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
748 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
749 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
750 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800751 return -EPERM;
752 }
753
Pratik Patel16aefdb2012-05-30 10:41:23 -0700754 val1 = drvdata->addr_val[idx];
755 val2 = drvdata->addr_val[idx + 1];
756 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700757 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800758}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800759
Pratik Patela9c0e062012-05-28 13:45:35 -0700760static ssize_t etm_store_addr_range(struct device *dev,
761 struct device_attribute *attr,
762 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800763{
764 unsigned long val1, val2;
765 uint8_t idx;
766
767 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
768 return -EINVAL;
769 /* lower address comparator cannot have a higher address value */
770 if (val1 > val2)
771 return -EINVAL;
772
Pratik Patel16aefdb2012-05-30 10:41:23 -0700773 mutex_lock(&drvdata->mutex);
774 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800775 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700776 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800777 return -EPERM;
778 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700779 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
780 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
781 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
782 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
783 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800784 return -EPERM;
785 }
786
Pratik Patel16aefdb2012-05-30 10:41:23 -0700787 drvdata->addr_val[idx] = val1;
788 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
789 drvdata->addr_val[idx + 1] = val2;
790 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
791 drvdata->enable_ctrl1 |= (1 << (idx/2));
792 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700793 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800794}
Pratik Patela9c0e062012-05-28 13:45:35 -0700795static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
796 etm_store_addr_range);
797
798static ssize_t etm_show_addr_start(struct device *dev,
799 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800800{
Pratik Patela9c0e062012-05-28 13:45:35 -0700801 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800802 uint8_t idx;
803
Pratik Patel16aefdb2012-05-30 10:41:23 -0700804 mutex_lock(&drvdata->mutex);
805 idx = drvdata->addr_idx;
806 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
807 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
808 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800809 return -EPERM;
810 }
811
Pratik Patel16aefdb2012-05-30 10:41:23 -0700812 val = drvdata->addr_val[idx];
813 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700814 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800815}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800816
Pratik Patela9c0e062012-05-28 13:45:35 -0700817static ssize_t etm_store_addr_start(struct device *dev,
818 struct device_attribute *attr,
819 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800820{
821 unsigned long val;
822 uint8_t idx;
823
824 if (sscanf(buf, "%lx", &val) != 1)
825 return -EINVAL;
826
Pratik Patel16aefdb2012-05-30 10:41:23 -0700827 mutex_lock(&drvdata->mutex);
828 idx = drvdata->addr_idx;
829 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
830 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
831 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800832 return -EPERM;
833 }
834
Pratik Patel16aefdb2012-05-30 10:41:23 -0700835 drvdata->addr_val[idx] = val;
836 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
837 drvdata->startstop_ctrl |= (1 << idx);
838 drvdata->enable_ctrl1 |= BIT(25);
839 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700840 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800841}
Pratik Patela9c0e062012-05-28 13:45:35 -0700842static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
843 etm_store_addr_start);
844
845static ssize_t etm_show_addr_stop(struct device *dev,
846 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800847{
848 unsigned long val;
849 uint8_t idx;
850
Pratik Patel16aefdb2012-05-30 10:41:23 -0700851 mutex_lock(&drvdata->mutex);
852 idx = drvdata->addr_idx;
853 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
854 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
855 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800856 return -EPERM;
857 }
858
Pratik Patel16aefdb2012-05-30 10:41:23 -0700859 val = drvdata->addr_val[idx];
860 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800861 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
862}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800863
Pratik Patela9c0e062012-05-28 13:45:35 -0700864static ssize_t etm_store_addr_stop(struct device *dev,
865 struct device_attribute *attr,
866 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800867{
868 unsigned long val;
869 uint8_t idx;
870
871 if (sscanf(buf, "%lx", &val) != 1)
872 return -EINVAL;
873
Pratik Patel16aefdb2012-05-30 10:41:23 -0700874 mutex_lock(&drvdata->mutex);
875 idx = drvdata->addr_idx;
876 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
877 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
878 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800879 return -EPERM;
880 }
881
Pratik Patel16aefdb2012-05-30 10:41:23 -0700882 drvdata->addr_val[idx] = val;
883 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
884 drvdata->startstop_ctrl |= (1 << (idx + 16));
885 drvdata->enable_ctrl1 |= BIT(25);
886 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700887 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800888}
Pratik Patela9c0e062012-05-28 13:45:35 -0700889static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
890 etm_store_addr_stop);
891
892static ssize_t etm_show_addr_acctype(struct device *dev,
893 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800894{
895 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800896
Pratik Patel16aefdb2012-05-30 10:41:23 -0700897 mutex_lock(&drvdata->mutex);
898 val = drvdata->addr_acctype[drvdata->addr_idx];
899 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800900 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
901}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800902
Pratik Patela9c0e062012-05-28 13:45:35 -0700903static ssize_t etm_store_addr_acctype(struct device *dev,
904 struct device_attribute *attr,
905 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800906{
907 unsigned long val;
908
909 if (sscanf(buf, "%lx", &val) != 1)
910 return -EINVAL;
911
Pratik Patel16aefdb2012-05-30 10:41:23 -0700912 mutex_lock(&drvdata->mutex);
913 drvdata->addr_acctype[drvdata->addr_idx] = val;
914 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700915 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800916}
Pratik Patela9c0e062012-05-28 13:45:35 -0700917static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
918 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800919
Pratik Patela9c0e062012-05-28 13:45:35 -0700920static ssize_t etm_show_cntr_idx(struct device *dev,
921 struct device_attribute *attr, char *buf)
922{
Pratik Patel16aefdb2012-05-30 10:41:23 -0700923 unsigned long val = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800924 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
925}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800926
Pratik Patela9c0e062012-05-28 13:45:35 -0700927static ssize_t etm_store_cntr_idx(struct device *dev,
928 struct device_attribute *attr,
929 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800930{
931 unsigned long val;
932
933 if (sscanf(buf, "%lx", &val) != 1)
934 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700935 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800936 return -EINVAL;
937
938 /* Use mutex to ensure index doesn't change while it gets dereferenced
939 * multiple times within a mutex block elsewhere.
940 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700941 mutex_lock(&drvdata->mutex);
942 drvdata->cntr_idx = val;
943 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700944 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800945}
Pratik Patela9c0e062012-05-28 13:45:35 -0700946static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
947 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800948
Pratik Patela9c0e062012-05-28 13:45:35 -0700949static ssize_t etm_show_cntr_rld_val(struct device *dev,
950 struct device_attribute *attr, char *buf)
951{
952 unsigned long val;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700953 mutex_lock(&drvdata->mutex);
954 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
955 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700956 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
957}
958
959static ssize_t etm_store_cntr_rld_val(struct device *dev,
960 struct device_attribute *attr,
961 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800962{
963 unsigned long val;
964
965 if (sscanf(buf, "%lx", &val) != 1)
966 return -EINVAL;
967
Pratik Patel16aefdb2012-05-30 10:41:23 -0700968 mutex_lock(&drvdata->mutex);
969 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
970 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700971 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800972}
Pratik Patela9c0e062012-05-28 13:45:35 -0700973static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
974 etm_store_cntr_rld_val);
975
976static ssize_t etm_show_cntr_event(struct device *dev,
977 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800978{
979 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700980
Pratik Patel16aefdb2012-05-30 10:41:23 -0700981 mutex_lock(&drvdata->mutex);
982 val = drvdata->cntr_event[drvdata->cntr_idx];
983 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800984 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
985}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800986
Pratik Patela9c0e062012-05-28 13:45:35 -0700987static ssize_t etm_store_cntr_event(struct device *dev,
988 struct device_attribute *attr,
989 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800990{
991 unsigned long val;
992
993 if (sscanf(buf, "%lx", &val) != 1)
994 return -EINVAL;
995
Pratik Patel16aefdb2012-05-30 10:41:23 -0700996 mutex_lock(&drvdata->mutex);
997 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
998 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700999 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001000}
Pratik Patela9c0e062012-05-28 13:45:35 -07001001static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
1002 etm_store_cntr_event);
1003
1004static ssize_t etm_show_cntr_rld_event(struct device *dev,
1005 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001006{
1007 unsigned long val;
1008
Pratik Patel16aefdb2012-05-30 10:41:23 -07001009 mutex_lock(&drvdata->mutex);
1010 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
1011 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001012 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1013}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001014
Pratik Patela9c0e062012-05-28 13:45:35 -07001015static ssize_t etm_store_cntr_rld_event(struct device *dev,
1016 struct device_attribute *attr,
1017 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001018{
1019 unsigned long val;
1020
1021 if (sscanf(buf, "%lx", &val) != 1)
1022 return -EINVAL;
1023
Pratik Patel16aefdb2012-05-30 10:41:23 -07001024 mutex_lock(&drvdata->mutex);
1025 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1026 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001027 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001028}
Pratik Patela9c0e062012-05-28 13:45:35 -07001029static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1030 etm_store_cntr_rld_event);
1031
1032static ssize_t etm_show_cntr_val(struct device *dev,
1033 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001034{
1035 unsigned long val;
1036
Pratik Patel16aefdb2012-05-30 10:41:23 -07001037 mutex_lock(&drvdata->mutex);
1038 val = drvdata->cntr_val[drvdata->cntr_idx];
1039 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001040 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1041}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001042
Pratik Patela9c0e062012-05-28 13:45:35 -07001043static ssize_t etm_store_cntr_val(struct device *dev,
1044 struct device_attribute *attr,
1045 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001046{
1047 unsigned long val;
1048
1049 if (sscanf(buf, "%lx", &val) != 1)
1050 return -EINVAL;
1051
Pratik Patel16aefdb2012-05-30 10:41:23 -07001052 mutex_lock(&drvdata->mutex);
1053 drvdata->cntr_val[drvdata->cntr_idx] = val;
1054 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001055 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001056}
Pratik Patela9c0e062012-05-28 13:45:35 -07001057static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1058 etm_store_cntr_val);
1059
1060static ssize_t etm_show_seq_12_event(struct device *dev,
1061 struct device_attribute *attr, char *buf)
1062{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001063 unsigned long val = drvdata->seq_12_event;
Pratik Patela9c0e062012-05-28 13:45:35 -07001064 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1065}
1066
1067static ssize_t etm_store_seq_12_event(struct device *dev,
1068 struct device_attribute *attr,
1069 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001070{
1071 unsigned long val;
1072
Pratik Patela9c0e062012-05-28 13:45:35 -07001073 if (sscanf(buf, "%lx", &val) != 1)
1074 return -EINVAL;
1075
Pratik Patel16aefdb2012-05-30 10:41:23 -07001076 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001077 return size;
1078}
1079static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1080 etm_store_seq_12_event);
1081
1082static ssize_t etm_show_seq_21_event(struct device *dev,
1083 struct device_attribute *attr, char *buf)
1084{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001085 unsigned long val = drvdata->seq_21_event;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001086 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1087}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001088
Pratik Patela9c0e062012-05-28 13:45:35 -07001089static ssize_t etm_store_seq_21_event(struct device *dev,
1090 struct device_attribute *attr,
1091 const char *buf, size_t size)
1092{
1093 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001094
Pratik Patela9c0e062012-05-28 13:45:35 -07001095 if (sscanf(buf, "%lx", &val) != 1)
1096 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001097
Pratik Patel16aefdb2012-05-30 10:41:23 -07001098 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001099 return size;
1100}
1101static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1102 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001103
Pratik Patela9c0e062012-05-28 13:45:35 -07001104static ssize_t etm_show_seq_23_event(struct device *dev,
1105 struct device_attribute *attr, char *buf)
1106{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001107 unsigned long val = drvdata->seq_23_event;
Pratik Patela9c0e062012-05-28 13:45:35 -07001108 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1109}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001110
Pratik Patela9c0e062012-05-28 13:45:35 -07001111static ssize_t etm_store_seq_23_event(struct device *dev,
1112 struct device_attribute *attr,
1113 const char *buf, size_t size)
1114{
1115 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001116
Pratik Patela9c0e062012-05-28 13:45:35 -07001117 if (sscanf(buf, "%lx", &val) != 1)
1118 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001119
Pratik Patel16aefdb2012-05-30 10:41:23 -07001120 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001121 return size;
1122}
1123static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1124 etm_store_seq_23_event);
1125
1126static ssize_t etm_show_seq_31_event(struct device *dev,
1127 struct device_attribute *attr, char *buf)
1128{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001129 unsigned long val = drvdata->seq_31_event;
Pratik Patela9c0e062012-05-28 13:45:35 -07001130 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1131}
1132
1133static ssize_t etm_store_seq_31_event(struct device *dev,
1134 struct device_attribute *attr,
1135 const char *buf, size_t size)
1136{
1137 unsigned long val;
1138
1139 if (sscanf(buf, "%lx", &val) != 1)
1140 return -EINVAL;
1141
Pratik Patel16aefdb2012-05-30 10:41:23 -07001142 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001143 return size;
1144}
1145static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1146 etm_store_seq_31_event);
1147
1148static ssize_t etm_show_seq_32_event(struct device *dev,
1149 struct device_attribute *attr, char *buf)
1150{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001151 unsigned long val = drvdata->seq_32_event;
Pratik Patela9c0e062012-05-28 13:45:35 -07001152 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1153}
1154
1155static ssize_t etm_store_seq_32_event(struct device *dev,
1156 struct device_attribute *attr,
1157 const char *buf, size_t size)
1158{
1159 unsigned long val;
1160
1161 if (sscanf(buf, "%lx", &val) != 1)
1162 return -EINVAL;
1163
Pratik Patel16aefdb2012-05-30 10:41:23 -07001164 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001165 return size;
1166}
1167static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1168 etm_store_seq_32_event);
1169
1170static ssize_t etm_show_seq_13_event(struct device *dev,
1171 struct device_attribute *attr, char *buf)
1172{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001173 unsigned long val = drvdata->seq_13_event;
Pratik Patela9c0e062012-05-28 13:45:35 -07001174 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1175}
1176
1177static ssize_t etm_store_seq_13_event(struct device *dev,
1178 struct device_attribute *attr,
1179 const char *buf, size_t size)
1180{
1181 unsigned long val;
1182
1183 if (sscanf(buf, "%lx", &val) != 1)
1184 return -EINVAL;
1185
Pratik Patel16aefdb2012-05-30 10:41:23 -07001186 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001187 return size;
1188}
1189static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1190 etm_store_seq_13_event);
1191
1192static ssize_t etm_show_seq_curr_state(struct device *dev,
1193 struct device_attribute *attr, char *buf)
1194{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001195 unsigned long val = drvdata->seq_curr_state;
Pratik Patela9c0e062012-05-28 13:45:35 -07001196 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1197}
1198
1199static ssize_t etm_store_seq_curr_state(struct device *dev,
1200 struct device_attribute *attr,
1201 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001202{
1203 unsigned long val;
1204
1205 if (sscanf(buf, "%lx", &val) != 1)
1206 return -EINVAL;
1207 if (val > ETM_SEQ_STATE_MAX_VAL)
1208 return -EINVAL;
1209
Pratik Patel16aefdb2012-05-30 10:41:23 -07001210 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001211 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001212}
Pratik Patela9c0e062012-05-28 13:45:35 -07001213static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1214 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001215
Pratik Patela9c0e062012-05-28 13:45:35 -07001216static ssize_t etm_show_ctxid_idx(struct device *dev,
1217 struct device_attribute *attr, char *buf)
1218{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001219 unsigned long val = drvdata->ctxid_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -07001220 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1221}
1222
1223static ssize_t etm_store_ctxid_idx(struct device *dev,
1224 struct device_attribute *attr,
1225 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001226{
1227 unsigned long val;
1228
1229 if (sscanf(buf, "%lx", &val) != 1)
1230 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001231 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001232 return -EINVAL;
1233
1234 /* Use mutex to ensure index doesn't change while it gets dereferenced
1235 * multiple times within a mutex block elsewhere.
1236 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001237 mutex_lock(&drvdata->mutex);
1238 drvdata->ctxid_idx = val;
1239 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001240 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001241}
Pratik Patela9c0e062012-05-28 13:45:35 -07001242static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1243 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001244
Pratik Patela9c0e062012-05-28 13:45:35 -07001245static ssize_t etm_show_ctxid_val(struct device *dev,
1246 struct device_attribute *attr, char *buf)
1247{
1248 unsigned long val;
1249
Pratik Patel16aefdb2012-05-30 10:41:23 -07001250 mutex_lock(&drvdata->mutex);
1251 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1252 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001253 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1254}
1255
1256static ssize_t etm_store_ctxid_val(struct device *dev,
1257 struct device_attribute *attr,
1258 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001259{
1260 unsigned long val;
1261
1262 if (sscanf(buf, "%lx", &val) != 1)
1263 return -EINVAL;
1264
Pratik Patel16aefdb2012-05-30 10:41:23 -07001265 mutex_lock(&drvdata->mutex);
1266 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1267 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001268 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001269}
Pratik Patela9c0e062012-05-28 13:45:35 -07001270static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1271 etm_store_ctxid_val);
1272
1273static ssize_t etm_show_ctxid_mask(struct device *dev,
1274 struct device_attribute *attr, char *buf)
1275{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001276 unsigned long val = drvdata->ctxid_mask;
Pratik Patela9c0e062012-05-28 13:45:35 -07001277 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1278}
1279
1280static ssize_t etm_store_ctxid_mask(struct device *dev,
1281 struct device_attribute *attr,
1282 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001283{
1284 unsigned long val;
1285
Pratik Patela9c0e062012-05-28 13:45:35 -07001286 if (sscanf(buf, "%lx", &val) != 1)
1287 return -EINVAL;
1288
Pratik Patel16aefdb2012-05-30 10:41:23 -07001289 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001290 return size;
1291}
1292static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1293 etm_store_ctxid_mask);
1294
1295static ssize_t etm_show_sync_freq(struct device *dev,
1296 struct device_attribute *attr, char *buf)
1297{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001298 unsigned long val = drvdata->sync_freq;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001299 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1300}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001301
Pratik Patela9c0e062012-05-28 13:45:35 -07001302static ssize_t etm_store_sync_freq(struct device *dev,
1303 struct device_attribute *attr,
1304 const char *buf, size_t size)
1305{
1306 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001307
Pratik Patela9c0e062012-05-28 13:45:35 -07001308 if (sscanf(buf, "%lx", &val) != 1)
1309 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001310
Pratik Patel16aefdb2012-05-30 10:41:23 -07001311 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001312 return size;
1313}
1314static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1315 etm_store_sync_freq);
1316
1317static ssize_t etm_show_timestamp_event(struct device *dev,
1318 struct device_attribute *attr,
1319 char *buf)
1320{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001321 unsigned long val = drvdata->timestamp_event;
Pratik Patela9c0e062012-05-28 13:45:35 -07001322 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1323}
1324
1325static ssize_t etm_store_timestamp_event(struct device *dev,
1326 struct device_attribute *attr,
1327 const char *buf, size_t size)
1328{
1329 unsigned long val;
1330
1331 if (sscanf(buf, "%lx", &val) != 1)
1332 return -EINVAL;
1333
Pratik Patel16aefdb2012-05-30 10:41:23 -07001334 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001335 return size;
1336}
1337static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1338 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001339
1340static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001341 &dev_attr_nr_addr_cmp.attr,
1342 &dev_attr_nr_cntr.attr,
1343 &dev_attr_nr_ctxid_cmp.attr,
1344 &dev_attr_reset.attr,
1345 &dev_attr_mode.attr,
1346 &dev_attr_trigger_event.attr,
1347 &dev_attr_enable_event.attr,
1348 &dev_attr_fifofull_level.attr,
1349 &dev_attr_addr_idx.attr,
1350 &dev_attr_addr_single.attr,
1351 &dev_attr_addr_range.attr,
1352 &dev_attr_addr_start.attr,
1353 &dev_attr_addr_stop.attr,
1354 &dev_attr_addr_acctype.attr,
1355 &dev_attr_cntr_idx.attr,
1356 &dev_attr_cntr_rld_val.attr,
1357 &dev_attr_cntr_event.attr,
1358 &dev_attr_cntr_rld_event.attr,
1359 &dev_attr_cntr_val.attr,
1360 &dev_attr_seq_12_event.attr,
1361 &dev_attr_seq_21_event.attr,
1362 &dev_attr_seq_23_event.attr,
1363 &dev_attr_seq_31_event.attr,
1364 &dev_attr_seq_32_event.attr,
1365 &dev_attr_seq_13_event.attr,
1366 &dev_attr_seq_curr_state.attr,
1367 &dev_attr_ctxid_idx.attr,
1368 &dev_attr_ctxid_val.attr,
1369 &dev_attr_ctxid_mask.attr,
1370 &dev_attr_sync_freq.attr,
1371 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001372 NULL,
1373};
1374
1375static struct attribute_group etm_attr_grp = {
1376 .attrs = etm_attrs,
1377};
1378
Stephen Boyda9510502012-04-24 16:23:34 -07001379static int __devinit etm_sysfs_init(void)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001380{
1381 int ret;
1382
Pratik Patel16aefdb2012-05-30 10:41:23 -07001383 drvdata->kobj = kobject_create_and_add("etm", qdss_get_modulekobj());
1384 if (!drvdata->kobj) {
1385 dev_err(drvdata->dev, "failed to create ETM sysfs kobject\n");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001386 ret = -ENOMEM;
1387 goto err_create;
1388 }
1389
Pratik Patel16aefdb2012-05-30 10:41:23 -07001390 ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001391 if (ret) {
Pratik Patel16aefdb2012-05-30 10:41:23 -07001392 dev_err(drvdata->dev, "failed to create ETM sysfs enabled"
Pratik Patel6630ebe2012-03-06 16:44:22 -08001393 " attribute\n");
1394 goto err_file;
1395 }
1396
Pratik Patel16aefdb2012-05-30 10:41:23 -07001397 if (sysfs_create_group(drvdata->kobj, &etm_attr_grp))
1398 dev_err(drvdata->dev, "failed to create ETM sysfs group\n");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001399
1400 return 0;
1401err_file:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001402 kobject_put(drvdata->kobj);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001403err_create:
1404 return ret;
1405}
1406
Stephen Boyda9510502012-04-24 16:23:34 -07001407static void __devexit etm_sysfs_exit(void)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001408{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001409 sysfs_remove_group(drvdata->kobj, &etm_attr_grp);
1410 sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
1411 kobject_put(drvdata->kobj);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001412}
1413
Stephen Boyda9510502012-04-24 16:23:34 -07001414static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001415{
Pratik Patel61de7302012-03-07 12:06:10 -08001416 switch (arch) {
1417 case PFT_ARCH_V1_1:
1418 break;
1419 default:
1420 return false;
1421 }
1422 return true;
1423}
1424
Pratik Patel16aefdb2012-05-30 10:41:23 -07001425static int __devinit etm_init_arch_data(void)
Pratik Patel61de7302012-03-07 12:06:10 -08001426{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001427 int ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001428 /* use cpu 0 for setup */
1429 int cpu = 0;
Pratik Patel61de7302012-03-07 12:06:10 -08001430 uint32_t etmidr;
1431 uint32_t etmccr;
Pratik Patel7831c082011-06-08 21:44:37 -07001432
Pratik Patel17f3b822011-11-21 12:41:47 -08001433 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel492b3012012-03-06 14:22:30 -08001434 etm_os_unlock(NULL);
1435 smp_call_function(etm_os_unlock, NULL, 1);
1436 ETM_UNLOCK(cpu);
Pratik Patel17f3b822011-11-21 12:41:47 -08001437 /* Vote for ETM power/clock enable */
Pratik Patel61de7302012-03-07 12:06:10 -08001438 etm_clr_pwrdwn(cpu);
1439 /* Set prog bit. It will be set from reset but this is included to
1440 * ensure it is set
1441 */
Pratik Patel492b3012012-03-06 14:22:30 -08001442 etm_set_prog(cpu);
Pratik Patel7831c082011-06-08 21:44:37 -07001443
1444 /* find all capabilities */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001445 etmidr = etm_readl(drvdata, cpu, ETMIDR);
1446 drvdata->arch = BMVAL(etmidr, 4, 11);
1447 if (etm_arch_supported(drvdata->arch) == false) {
Pratik Patel61de7302012-03-07 12:06:10 -08001448 ret = -EINVAL;
1449 goto err;
1450 }
Pratik Patel7831c082011-06-08 21:44:37 -07001451
Pratik Patel16aefdb2012-05-30 10:41:23 -07001452 etmccr = etm_readl(drvdata, cpu, ETMCCR);
1453 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1454 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1455 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1456 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1457 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001458
Pratik Patel17f3b822011-11-21 12:41:47 -08001459 /* Vote for ETM power/clock disable */
Pratik Patel61de7302012-03-07 12:06:10 -08001460 etm_set_pwrdwn(cpu);
Pratik Patel492b3012012-03-06 14:22:30 -08001461 ETM_LOCK(cpu);
Pratik Patel61de7302012-03-07 12:06:10 -08001462
1463 return 0;
1464err:
1465 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001466}
1467
Pratik Patel16aefdb2012-05-30 10:41:23 -07001468static void __devinit etm_init_default_data(void)
1469{
1470 int i;
1471
1472 drvdata->trigger_event = 0x406F;
1473 drvdata->enable_event = 0x6F;
1474 drvdata->enable_ctrl1 = 0x1;
1475 drvdata->fifofull_level = 0x28;
1476 if (drvdata->nr_addr_cmp >= 2) {
1477 drvdata->addr_val[0] = (uint32_t) _stext;
1478 drvdata->addr_val[1] = (uint32_t) _etext;
1479 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1480 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1481 }
1482 for (i = 0; i < drvdata->nr_cntr; i++) {
1483 drvdata->cntr_event[i] = 0x406F;
1484 drvdata->cntr_rld_event[i] = 0x406F;
1485 }
1486 drvdata->seq_12_event = 0x406F;
1487 drvdata->seq_21_event = 0x406F;
1488 drvdata->seq_23_event = 0x406F;
1489 drvdata->seq_31_event = 0x406F;
1490 drvdata->seq_32_event = 0x406F;
1491 drvdata->seq_13_event = 0x406F;
1492 drvdata->sync_freq = 0x80;
1493 drvdata->timestamp_event = 0x406F;
1494
1495 /* Overrides for Krait pass1 */
1496 if (cpu_is_krait_v1()) {
1497 /* Krait pass1 doesn't support include filtering and non-cycle
1498 * accurate tracing
1499 */
1500 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1501 drvdata->ctrl = 0x1000;
1502 drvdata->enable_ctrl1 = 0x1000000;
1503 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1504 drvdata->addr_val[i] = 0x0;
1505 drvdata->addr_acctype[i] = 0x0;
1506 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1507 }
1508 }
1509}
1510
Pratik Patel492b3012012-03-06 14:22:30 -08001511static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001512{
Pratik Patele5771792011-09-17 18:33:54 -07001513 int ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001514 struct resource *res;
1515
Pratik Patel16aefdb2012-05-30 10:41:23 -07001516 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
1517 if (!drvdata) {
1518 ret = -ENOMEM;
1519 goto err_kzalloc_drvdata;
1520 }
1521
Pratik Patel7831c082011-06-08 21:44:37 -07001522 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1523 if (!res) {
1524 ret = -EINVAL;
1525 goto err_res;
1526 }
1527
Pratik Patel16aefdb2012-05-30 10:41:23 -07001528 drvdata->base = ioremap_nocache(res->start, resource_size(res));
1529 if (!drvdata->base) {
Pratik Patel7831c082011-06-08 21:44:37 -07001530 ret = -EINVAL;
1531 goto err_ioremap;
1532 }
1533
Pratik Patel16aefdb2012-05-30 10:41:23 -07001534 drvdata->dev = &pdev->dev;
Pratik Patel7831c082011-06-08 21:44:37 -07001535
Pratik Patel16aefdb2012-05-30 10:41:23 -07001536 mutex_init(&drvdata->mutex);
1537 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
1538 pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
1539 PM_QOS_DEFAULT_VALUE);
1540 drvdata->src = qdss_get("msm_etm");
1541 if (IS_ERR(drvdata->src)) {
1542 ret = PTR_ERR(drvdata->src);
Pratik Patele10a77c2012-03-20 10:35:16 -07001543 goto err_qdssget;
1544 }
1545
Pratik Patel16aefdb2012-05-30 10:41:23 -07001546 drvdata->clk = clk_get(drvdata->dev, "core_clk");
1547 if (IS_ERR(drvdata->clk)) {
1548 ret = PTR_ERR(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001549 goto err_clk_get;
1550 }
1551
Pratik Patel16aefdb2012-05-30 10:41:23 -07001552 ret = clk_set_rate(drvdata->clk, CS_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001553 if (ret)
Pratik Patelf17b1472012-05-25 22:23:52 -07001554 goto err_clk_rate;
1555
Pratik Patel16aefdb2012-05-30 10:41:23 -07001556 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001557 if (ret)
1558 goto err_clk_enable;
Pratik Patel7831c082011-06-08 21:44:37 -07001559
Pratik Patel16aefdb2012-05-30 10:41:23 -07001560 ret = etm_init_arch_data();
Pratik Patel61de7302012-03-07 12:06:10 -08001561 if (ret)
1562 goto err_arch;
Pratik Patel7831c082011-06-08 21:44:37 -07001563
Pratik Patel16aefdb2012-05-30 10:41:23 -07001564 etm_init_default_data();
1565
Pratik Patel6630ebe2012-03-06 16:44:22 -08001566 ret = etm_sysfs_init();
1567 if (ret)
1568 goto err_sysfs;
1569
Pratik Patel16aefdb2012-05-30 10:41:23 -07001570 drvdata->enabled = false;
Pratik Patel7831c082011-06-08 21:44:37 -07001571
Pratik Patel16aefdb2012-05-30 10:41:23 -07001572 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001573
Pratik Patel16aefdb2012-05-30 10:41:23 -07001574 dev_info(drvdata->dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001575
Pratik Patel61de7302012-03-07 12:06:10 -08001576 if (etm_boot_enable)
1577 etm_enable();
Pratik Patel7831c082011-06-08 21:44:37 -07001578
1579 return 0;
1580
Pratik Patel6630ebe2012-03-06 16:44:22 -08001581err_sysfs:
Pratik Patel61de7302012-03-07 12:06:10 -08001582err_arch:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001583 clk_disable_unprepare(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001584err_clk_enable:
1585err_clk_rate:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001586 clk_put(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001587err_clk_get:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001588 qdss_put(drvdata->src);
Pratik Patele10a77c2012-03-20 10:35:16 -07001589err_qdssget:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001590 pm_qos_remove_request(&drvdata->qos_req);
1591 wake_lock_destroy(&drvdata->wake_lock);
1592 mutex_destroy(&drvdata->mutex);
1593 iounmap(drvdata->base);
Pratik Patel7831c082011-06-08 21:44:37 -07001594err_ioremap:
1595err_res:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001596 kfree(drvdata);
1597err_kzalloc_drvdata:
1598 dev_err(drvdata->dev, "ETM init failed\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001599 return ret;
1600}
1601
Pratik Patelf6fe9182012-03-20 14:04:18 -07001602static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001603{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001604 if (drvdata->enabled)
Pratik Patel61de7302012-03-07 12:06:10 -08001605 etm_disable();
Pratik Patel6630ebe2012-03-06 16:44:22 -08001606 etm_sysfs_exit();
Pratik Patel16aefdb2012-05-30 10:41:23 -07001607 clk_put(drvdata->clk);
1608 qdss_put(drvdata->src);
1609 pm_qos_remove_request(&drvdata->qos_req);
1610 wake_lock_destroy(&drvdata->wake_lock);
1611 mutex_destroy(&drvdata->mutex);
1612 iounmap(drvdata->base);
1613 kfree(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001614
1615 return 0;
1616}
1617
Pratik Patel9eae4822012-05-14 17:34:53 -07001618static struct of_device_id etm_match[] = {
1619 {.compatible = "qcom,msm-etm"},
1620 {}
1621};
1622
Pratik Patel492b3012012-03-06 14:22:30 -08001623static struct platform_driver etm_driver = {
1624 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001625 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001626 .driver = {
Pratik Patel492b3012012-03-06 14:22:30 -08001627 .name = "msm_etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001628 .owner = THIS_MODULE,
1629 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001630 },
1631};
1632
Pratik Patel492b3012012-03-06 14:22:30 -08001633int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001634{
Pratik Patel492b3012012-03-06 14:22:30 -08001635 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001636}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001637module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001638
Pratik Patelf6fe9182012-03-20 14:04:18 -07001639void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001640{
Pratik Patel492b3012012-03-06 14:22:30 -08001641 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001642}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001643module_exit(etm_exit);
1644
1645MODULE_LICENSE("GPL v2");
1646MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");