blob: 020e54236d9f04356a989a4a46e2d0769f412cc8 [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 Patel3b0ca882012-06-01 16:54:14 -070029#include <linux/mutex.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070030#include <linux/clk.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070031#include <linux/coresight.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080032#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080033#include <mach/socinfo.h>
Pratik Patel7831c082011-06-08 21:44:37 -070034
Pratik Patel1746b8f2012-06-02 21:11:41 -070035#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070036
Pratik Patel3b0ca882012-06-01 16:54:14 -070037
38#define etm_writel(drvdata, val, off) \
39 __raw_writel((val), drvdata->base + off)
40#define etm_readl(drvdata, off) \
41 __raw_readl(drvdata->base + off)
42
43#define ETM_LOCK(drvdata) \
44do { \
45 mb(); \
46 etm_writel(drvdata, 0x0, CORESIGHT_LAR); \
47} while (0)
48#define ETM_UNLOCK(drvdata) \
49do { \
50 etm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
51 mb(); \
52} while (0)
53
Pratik Patel7831c082011-06-08 21:44:37 -070054
55/*
56 * Device registers:
57 * 0x000 - 0x2FC: Trace registers
58 * 0x300 - 0x314: Management registers
59 * 0x318 - 0xEFC: Trace registers
60 *
61 * Coresight registers
62 * 0xF00 - 0xF9C: Management registers
63 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
64 * Trace registers in PFTv1.1
65 * 0xFA8 - 0xFFC: Management registers
66 */
67
68/* Trace registers (0x000-0x2FC) */
69#define ETMCR (0x000)
70#define ETMCCR (0x004)
71#define ETMTRIGGER (0x008)
72#define ETMSR (0x010)
73#define ETMSCR (0x014)
74#define ETMTSSCR (0x018)
75#define ETMTEEVR (0x020)
76#define ETMTECR1 (0x024)
77#define ETMFFLR (0x02C)
78#define ETMACVRn(n) (0x040 + (n * 4))
79#define ETMACTRn(n) (0x080 + (n * 4))
80#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
81#define ETMCNTENRn(n) (0x150 + (n * 4))
82#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
83#define ETMCNTVRn(n) (0x170 + (n * 4))
84#define ETMSQ12EVR (0x180)
85#define ETMSQ21EVR (0x184)
86#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -080087#define ETMSQ31EVR (0x18C)
88#define ETMSQ32EVR (0x190)
89#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -070090#define ETMSQR (0x19C)
91#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
92#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
93#define ETMCIDCMR (0x1BC)
94#define ETMIMPSPEC0 (0x1C0)
95#define ETMIMPSPEC1 (0x1C4)
96#define ETMIMPSPEC2 (0x1C8)
97#define ETMIMPSPEC3 (0x1CC)
98#define ETMIMPSPEC4 (0x1D0)
99#define ETMIMPSPEC5 (0x1D4)
100#define ETMIMPSPEC6 (0x1D8)
101#define ETMIMPSPEC7 (0x1DC)
102#define ETMSYNCFR (0x1E0)
103#define ETMIDR (0x1E4)
104#define ETMCCER (0x1E8)
105#define ETMEXTINSELR (0x1EC)
106#define ETMTESSEICR (0x1F0)
107#define ETMEIBCR (0x1F4)
108#define ETMTSEVR (0x1F8)
109#define ETMAUXCR (0x1FC)
110#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800111#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700112/* Management registers (0x300-0x314) */
113#define ETMOSLAR (0x300)
114#define ETMOSLSR (0x304)
115#define ETMOSSRR (0x308)
116#define ETMPDCR (0x310)
117#define ETMPDSR (0x314)
118
Pratik Patel3b0ca882012-06-01 16:54:14 -0700119
Pratik Patel61de7302012-03-07 12:06:10 -0800120#define ETM_MAX_ADDR_CMP (16)
121#define ETM_MAX_CNTR (4)
122#define ETM_MAX_CTXID_CMP (3)
123
Pratik Patel6630ebe2012-03-06 16:44:22 -0800124#define ETM_MODE_EXCLUDE BIT(0)
125#define ETM_MODE_CYCACC BIT(1)
126#define ETM_MODE_STALL BIT(2)
127#define ETM_MODE_TIMESTAMP BIT(3)
128#define ETM_MODE_CTXID BIT(4)
129#define ETM_MODE_ALL (0x1F)
130
131#define ETM_EVENT_MASK (0x1FFFF)
132#define ETM_SYNC_MASK (0xFFF)
133#define ETM_ALL_MASK (0xFFFFFFFF)
134
135#define ETM_SEQ_STATE_MAX_VAL (0x2)
136
Pratik Patel3b0ca882012-06-01 16:54:14 -0700137enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800138 ETM_ADDR_TYPE_NONE,
139 ETM_ADDR_TYPE_SINGLE,
140 ETM_ADDR_TYPE_RANGE,
141 ETM_ADDR_TYPE_START,
142 ETM_ADDR_TYPE_STOP,
143};
144
Pratik Patel6630ebe2012-03-06 16:44:22 -0800145
Pratik Patel29cba152012-01-03 11:40:26 -0800146#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700147static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800148#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700149static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800150#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700151module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700152 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700153);
154
Pratik Patel16aefdb2012-05-30 10:41:23 -0700155struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700156 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700157 struct device *dev;
158 struct coresight_device *csdev;
159 struct clk *clk;
160 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700161 struct wake_lock wake_lock;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700162 struct pm_qos_request qos_req;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700163 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800164 uint8_t arch;
165 uint8_t nr_addr_cmp;
166 uint8_t nr_cntr;
167 uint8_t nr_ext_inp;
168 uint8_t nr_ext_out;
169 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800170 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800171 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800172 uint32_t ctrl;
173 uint32_t trigger_event;
174 uint32_t startstop_ctrl;
175 uint32_t enable_event;
176 uint32_t enable_ctrl1;
177 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800178 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800179 uint32_t addr_val[ETM_MAX_ADDR_CMP];
180 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800181 uint32_t addr_type[ETM_MAX_ADDR_CMP];
182 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800183 uint32_t cntr_rld_val[ETM_MAX_CNTR];
184 uint32_t cntr_event[ETM_MAX_CNTR];
185 uint32_t cntr_rld_event[ETM_MAX_CNTR];
186 uint32_t cntr_val[ETM_MAX_CNTR];
187 uint32_t seq_12_event;
188 uint32_t seq_21_event;
189 uint32_t seq_23_event;
190 uint32_t seq_31_event;
191 uint32_t seq_32_event;
192 uint32_t seq_13_event;
193 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800194 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800195 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
196 uint32_t ctxid_mask;
197 uint32_t sync_freq;
198 uint32_t timestamp_event;
Pratik Patel7831c082011-06-08 21:44:37 -0700199};
200
Pratik Patel7831c082011-06-08 21:44:37 -0700201
Pratik Patel17f3b822011-11-21 12:41:47 -0800202/* ETM clock is derived from the processor clock and gets enabled on a
203 * logical OR of below items on Krait (pass2 onwards):
204 * 1.CPMR[ETMCLKEN] is 1
205 * 2.ETMCR[PD] is 0
206 * 3.ETMPDCR[PU] is 1
207 * 4.Reset is asserted (core or debug)
208 * 5.APB memory mapped requests (eg. EDAP access)
209 *
210 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
211 * enables
212 *
213 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
214 * clock vote in the driver and the save-restore code uses 1. above
215 * for its vote
216 */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700217static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700218{
219 uint32_t etmcr;
220
Pratik Patel3b0ca882012-06-01 16:54:14 -0700221 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700222 etmcr |= BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700223 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700224}
225
Pratik Patel3b0ca882012-06-01 16:54:14 -0700226static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700227{
228 uint32_t etmcr;
229
Pratik Patel3b0ca882012-06-01 16:54:14 -0700230 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700231 etmcr &= ~BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700232 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700233}
234
Pratik Patel3b0ca882012-06-01 16:54:14 -0700235static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700236{
237 uint32_t etmcr;
238 int count;
239
Pratik Patel3b0ca882012-06-01 16:54:14 -0700240 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700241 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700242 etm_writel(drvdata, etmcr, ETMCR);
243 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700244 && count > 0; count--)
245 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800246 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700247 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700248}
249
Pratik Patel3b0ca882012-06-01 16:54:14 -0700250static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700251{
252 uint32_t etmcr;
253 int count;
254
Pratik Patel3b0ca882012-06-01 16:54:14 -0700255 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700256 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700257 etm_writel(drvdata, etmcr, ETMCR);
258 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700259 && count > 0; count--)
260 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800261 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700262 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700263}
264
Pratik Patel3b0ca882012-06-01 16:54:14 -0700265static void __etm_enable(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700266{
Pratik Patel17f3b822011-11-21 12:41:47 -0800267 int i;
Pratik Patel7831c082011-06-08 21:44:37 -0700268
Pratik Patel3b0ca882012-06-01 16:54:14 -0700269 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800270 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700271 etm_clr_pwrdwn(drvdata);
272 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700273
Pratik Patel3b0ca882012-06-01 16:54:14 -0700274 etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
275 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
276 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
277 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
278 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
279 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700280 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700281 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
282 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700283 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700284 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700285 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
286 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
287 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700288 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700289 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800290 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700291 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
292 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
293 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
294 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
295 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
296 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
297 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700298 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700299 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700300 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700301 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
302 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
303 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
304 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
305 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
306 etm_writel(drvdata, 0x00000000, ETMAUXCR);
307 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
308 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800309
Pratik Patel3b0ca882012-06-01 16:54:14 -0700310 etm_clr_prog(drvdata);
311 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700312}
313
Pratik Patel3b0ca882012-06-01 16:54:14 -0700314static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700315{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700316 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
317 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800318
Pratik Patel16aefdb2012-05-30 10:41:23 -0700319 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700320 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700321 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700322 *
323 * we rely on the user to prevent hotplug on/off racing with this
324 * operation and to ensure cores where trace is expected to be turned
325 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700326 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700327 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700328
Pratik Patel16aefdb2012-05-30 10:41:23 -0700329 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700330 if (ret)
331 goto err_clk;
332
Pratik Patel3b0ca882012-06-01 16:54:14 -0700333 mutex_lock(&drvdata->mutex);
334 __etm_enable(drvdata);
335 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700336
Pratik Patel16aefdb2012-05-30 10:41:23 -0700337 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
338 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700339
Pratik Patel16aefdb2012-05-30 10:41:23 -0700340 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700341 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700342err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700343 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
344 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800345 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700346}
347
Pratik Patel3b0ca882012-06-01 16:54:14 -0700348static void __etm_disable(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700349{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700350 ETM_UNLOCK(drvdata);
351 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700352
Pratik Patel17f3b822011-11-21 12:41:47 -0800353 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700354 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700355
Pratik Patel17f3b822011-11-21 12:41:47 -0800356 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700357 etm_set_pwrdwn(drvdata);
358 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700359}
360
Pratik Patel3b0ca882012-06-01 16:54:14 -0700361static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700362{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700363 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800364
Pratik Patel16aefdb2012-05-30 10:41:23 -0700365 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700366 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700367 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700368 *
369 * we rely on the user to prevent hotplug on/off racing with this
370 * operation and to ensure cores where trace is expected to be turned
371 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700372 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700373 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700374
Pratik Patel3b0ca882012-06-01 16:54:14 -0700375 mutex_lock(&drvdata->mutex);
376 __etm_disable(drvdata);
377 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700378
Pratik Patel16aefdb2012-05-30 10:41:23 -0700379 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700380
Pratik Patel16aefdb2012-05-30 10:41:23 -0700381 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
382 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700383
Pratik Patel16aefdb2012-05-30 10:41:23 -0700384 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700385}
386
Pratik Patel3b0ca882012-06-01 16:54:14 -0700387static const struct coresight_ops_source etm_source_ops = {
388 .enable = etm_enable,
389 .disable = etm_disable,
390};
Pratik Patel17f3b822011-11-21 12:41:47 -0800391
Pratik Patel3b0ca882012-06-01 16:54:14 -0700392static const struct coresight_ops etm_cs_ops = {
393 .source_ops = &etm_source_ops,
394};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800395
Pratik Patela9c0e062012-05-28 13:45:35 -0700396static ssize_t etm_show_nr_addr_cmp(struct device *dev,
397 struct device_attribute *attr, char *buf)
398{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700399 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700400 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700401
Pratik Patela9c0e062012-05-28 13:45:35 -0700402 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
403}
404static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
405
406static ssize_t etm_show_nr_cntr(struct device *dev,
407 struct device_attribute *attr, char *buf)
408{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700409 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700410 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700411
Pratik Patela9c0e062012-05-28 13:45:35 -0700412 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
413}
414static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
415
416static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
417 struct device_attribute *attr, char *buf)
418{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700419 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700420 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700421
Pratik Patela9c0e062012-05-28 13:45:35 -0700422 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
423}
424static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
425
426static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
427 char *buf)
428{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700429 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700430 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700431
Pratik Patela9c0e062012-05-28 13:45:35 -0700432 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
433}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800434
Pratik Pateld30deda2012-02-01 14:40:55 -0800435/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700436static ssize_t etm_store_reset(struct device *dev,
437 struct device_attribute *attr, const char *buf,
438 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800439{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700440 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800441 int i;
442 unsigned long val;
443
444 if (sscanf(buf, "%lx", &val) != 1)
445 return -EINVAL;
446
Pratik Patel16aefdb2012-05-30 10:41:23 -0700447 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800448 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700449 drvdata->mode = ETM_MODE_EXCLUDE;
450 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800451 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700452 drvdata->mode |= ETM_MODE_CYCACC;
453 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800454 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700455 drvdata->trigger_event = 0x406F;
456 drvdata->startstop_ctrl = 0x0;
457 drvdata->enable_event = 0x6F;
458 drvdata->enable_ctrl1 = 0x1000000;
459 drvdata->fifofull_level = 0x28;
460 drvdata->addr_idx = 0x0;
461 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
462 drvdata->addr_val[i] = 0x0;
463 drvdata->addr_acctype[i] = 0x0;
464 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800465 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700466 drvdata->cntr_idx = 0x0;
467 for (i = 0; i < drvdata->nr_cntr; i++) {
468 drvdata->cntr_rld_val[i] = 0x0;
469 drvdata->cntr_event[i] = 0x406F;
470 drvdata->cntr_rld_event[i] = 0x406F;
471 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800472 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700473 drvdata->seq_12_event = 0x406F;
474 drvdata->seq_21_event = 0x406F;
475 drvdata->seq_23_event = 0x406F;
476 drvdata->seq_31_event = 0x406F;
477 drvdata->seq_32_event = 0x406F;
478 drvdata->seq_13_event = 0x406F;
479 drvdata->seq_curr_state = 0x0;
480 drvdata->ctxid_idx = 0x0;
481 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
482 drvdata->ctxid_val[i] = 0x0;
483 drvdata->ctxid_mask = 0x0;
484 drvdata->sync_freq = 0x80;
485 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800486 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700487 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700488 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800489}
Pratik Patela9c0e062012-05-28 13:45:35 -0700490static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800491
Pratik Patela9c0e062012-05-28 13:45:35 -0700492static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
493 char *buf)
494{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700495 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700496 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700497
Pratik Patela9c0e062012-05-28 13:45:35 -0700498 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
499}
500
501static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
502 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800503{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700504 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800505 unsigned long val;
506
507 if (sscanf(buf, "%lx", &val) != 1)
508 return -EINVAL;
509
Pratik Patel16aefdb2012-05-30 10:41:23 -0700510 mutex_lock(&drvdata->mutex);
511 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800512
Pratik Patel16aefdb2012-05-30 10:41:23 -0700513 if (drvdata->mode & ETM_MODE_EXCLUDE)
514 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800515 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700516 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800517
Pratik Patel16aefdb2012-05-30 10:41:23 -0700518 if (drvdata->mode & ETM_MODE_CYCACC)
519 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800520 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700521 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800522
Pratik Patel16aefdb2012-05-30 10:41:23 -0700523 if (drvdata->mode & ETM_MODE_STALL)
524 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800525 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700526 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800527
Pratik Patel16aefdb2012-05-30 10:41:23 -0700528 if (drvdata->mode & ETM_MODE_TIMESTAMP)
529 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800530 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700531 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700532
Pratik Patel16aefdb2012-05-30 10:41:23 -0700533 if (drvdata->mode & ETM_MODE_CTXID)
534 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800535 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700536 drvdata->ctrl &= ~(BIT(14) | BIT(15));
537 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800538
Pratik Patela9c0e062012-05-28 13:45:35 -0700539 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800540}
Pratik Patela9c0e062012-05-28 13:45:35 -0700541static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800542
Pratik Patela9c0e062012-05-28 13:45:35 -0700543static ssize_t etm_show_trigger_event(struct device *dev,
544 struct device_attribute *attr, char *buf)
545{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700546 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700547 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700548
Pratik Patela9c0e062012-05-28 13:45:35 -0700549 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
550}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800551
Pratik Patela9c0e062012-05-28 13:45:35 -0700552static ssize_t etm_store_trigger_event(struct device *dev,
553 struct device_attribute *attr,
554 const char *buf, size_t size)
555{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700556 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700557 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800558
Pratik Patela9c0e062012-05-28 13:45:35 -0700559 if (sscanf(buf, "%lx", &val) != 1)
560 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800561
Pratik Patel16aefdb2012-05-30 10:41:23 -0700562 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700563 return size;
564}
565static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
566 etm_store_trigger_event);
567
568static ssize_t etm_show_enable_event(struct device *dev,
569 struct device_attribute *attr, char *buf)
570{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700571 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700572 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700573
Pratik Patela9c0e062012-05-28 13:45:35 -0700574 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
575}
576
577static ssize_t etm_store_enable_event(struct device *dev,
578 struct device_attribute *attr,
579 const char *buf, size_t size)
580{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700581 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700582 unsigned long val;
583
584 if (sscanf(buf, "%lx", &val) != 1)
585 return -EINVAL;
586
Pratik Patel16aefdb2012-05-30 10:41:23 -0700587 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700588 return size;
589}
590static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
591 etm_store_enable_event);
592
593static ssize_t etm_show_fifofull_level(struct device *dev,
594 struct device_attribute *attr, char *buf)
595{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700596 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700597 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700598
Pratik Patela9c0e062012-05-28 13:45:35 -0700599 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
600}
601
602static ssize_t etm_store_fifofull_level(struct device *dev,
603 struct device_attribute *attr,
604 const char *buf, size_t size)
605{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700606 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700607 unsigned long val;
608
609 if (sscanf(buf, "%lx", &val) != 1)
610 return -EINVAL;
611
Pratik Patel16aefdb2012-05-30 10:41:23 -0700612 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700613 return size;
614}
615static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
616 etm_store_fifofull_level);
617
618static ssize_t etm_show_addr_idx(struct device *dev,
619 struct device_attribute *attr, char *buf)
620{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700621 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700622 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700623
Pratik Patela9c0e062012-05-28 13:45:35 -0700624 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
625}
626
627static ssize_t etm_store_addr_idx(struct device *dev,
628 struct device_attribute *attr,
629 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800630{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700631 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800632 unsigned long val;
633
634 if (sscanf(buf, "%lx", &val) != 1)
635 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700636 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800637 return -EINVAL;
638
639 /* Use mutex to ensure index doesn't change while it gets dereferenced
640 * multiple times within a mutex block elsewhere.
641 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700642 mutex_lock(&drvdata->mutex);
643 drvdata->addr_idx = val;
644 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700645 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800646}
Pratik Patela9c0e062012-05-28 13:45:35 -0700647static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
648 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800649
Pratik Patela9c0e062012-05-28 13:45:35 -0700650static ssize_t etm_show_addr_single(struct device *dev,
651 struct device_attribute *attr, char *buf)
652{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700653 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700654 unsigned long val;
655 uint8_t idx;
656
Pratik Patel16aefdb2012-05-30 10:41:23 -0700657 mutex_lock(&drvdata->mutex);
658 idx = drvdata->addr_idx;
659 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
660 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
661 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700662 return -EPERM;
663 }
664
Pratik Patel16aefdb2012-05-30 10:41:23 -0700665 val = drvdata->addr_val[idx];
666 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700667 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
668}
669
670static ssize_t etm_store_addr_single(struct device *dev,
671 struct device_attribute *attr,
672 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800673{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700674 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800675 unsigned long val;
676 uint8_t idx;
677
678 if (sscanf(buf, "%lx", &val) != 1)
679 return -EINVAL;
680
Pratik Patel16aefdb2012-05-30 10:41:23 -0700681 mutex_lock(&drvdata->mutex);
682 idx = drvdata->addr_idx;
683 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
684 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
685 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800686 return -EPERM;
687 }
688
Pratik Patel16aefdb2012-05-30 10:41:23 -0700689 drvdata->addr_val[idx] = val;
690 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
691 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700692 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800693}
Pratik Patela9c0e062012-05-28 13:45:35 -0700694static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
695 etm_store_addr_single);
696
697static ssize_t etm_show_addr_range(struct device *dev,
698 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800699{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700700 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700701 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800702 uint8_t idx;
703
Pratik Patel16aefdb2012-05-30 10:41:23 -0700704 mutex_lock(&drvdata->mutex);
705 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700706 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700707 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700708 return -EPERM;
709 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700710 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
711 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
712 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
713 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
714 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800715 return -EPERM;
716 }
717
Pratik Patel16aefdb2012-05-30 10:41:23 -0700718 val1 = drvdata->addr_val[idx];
719 val2 = drvdata->addr_val[idx + 1];
720 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700721 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800722}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800723
Pratik Patela9c0e062012-05-28 13:45:35 -0700724static ssize_t etm_store_addr_range(struct device *dev,
725 struct device_attribute *attr,
726 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800727{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700728 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800729 unsigned long val1, val2;
730 uint8_t idx;
731
732 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
733 return -EINVAL;
734 /* lower address comparator cannot have a higher address value */
735 if (val1 > val2)
736 return -EINVAL;
737
Pratik Patel16aefdb2012-05-30 10:41:23 -0700738 mutex_lock(&drvdata->mutex);
739 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800740 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700741 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800742 return -EPERM;
743 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700744 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
745 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
746 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
747 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
748 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800749 return -EPERM;
750 }
751
Pratik Patel16aefdb2012-05-30 10:41:23 -0700752 drvdata->addr_val[idx] = val1;
753 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
754 drvdata->addr_val[idx + 1] = val2;
755 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
756 drvdata->enable_ctrl1 |= (1 << (idx/2));
757 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700758 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800759}
Pratik Patela9c0e062012-05-28 13:45:35 -0700760static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
761 etm_store_addr_range);
762
763static ssize_t etm_show_addr_start(struct device *dev,
764 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800765{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700766 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700767 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800768 uint8_t idx;
769
Pratik Patel16aefdb2012-05-30 10:41:23 -0700770 mutex_lock(&drvdata->mutex);
771 idx = drvdata->addr_idx;
772 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
773 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
774 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800775 return -EPERM;
776 }
777
Pratik Patel16aefdb2012-05-30 10:41:23 -0700778 val = drvdata->addr_val[idx];
779 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700780 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800781}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800782
Pratik Patela9c0e062012-05-28 13:45:35 -0700783static ssize_t etm_store_addr_start(struct device *dev,
784 struct device_attribute *attr,
785 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800786{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700787 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800788 unsigned long val;
789 uint8_t idx;
790
791 if (sscanf(buf, "%lx", &val) != 1)
792 return -EINVAL;
793
Pratik Patel16aefdb2012-05-30 10:41:23 -0700794 mutex_lock(&drvdata->mutex);
795 idx = drvdata->addr_idx;
796 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
797 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
798 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800799 return -EPERM;
800 }
801
Pratik Patel16aefdb2012-05-30 10:41:23 -0700802 drvdata->addr_val[idx] = val;
803 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
804 drvdata->startstop_ctrl |= (1 << idx);
805 drvdata->enable_ctrl1 |= BIT(25);
806 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700807 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800808}
Pratik Patela9c0e062012-05-28 13:45:35 -0700809static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
810 etm_store_addr_start);
811
812static ssize_t etm_show_addr_stop(struct device *dev,
813 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800814{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700815 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800816 unsigned long val;
817 uint8_t idx;
818
Pratik Patel16aefdb2012-05-30 10:41:23 -0700819 mutex_lock(&drvdata->mutex);
820 idx = drvdata->addr_idx;
821 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
822 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
823 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800824 return -EPERM;
825 }
826
Pratik Patel16aefdb2012-05-30 10:41:23 -0700827 val = drvdata->addr_val[idx];
828 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800829 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
830}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800831
Pratik Patela9c0e062012-05-28 13:45:35 -0700832static ssize_t etm_store_addr_stop(struct device *dev,
833 struct device_attribute *attr,
834 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800835{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700836 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800837 unsigned long val;
838 uint8_t idx;
839
840 if (sscanf(buf, "%lx", &val) != 1)
841 return -EINVAL;
842
Pratik Patel16aefdb2012-05-30 10:41:23 -0700843 mutex_lock(&drvdata->mutex);
844 idx = drvdata->addr_idx;
845 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
846 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
847 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800848 return -EPERM;
849 }
850
Pratik Patel16aefdb2012-05-30 10:41:23 -0700851 drvdata->addr_val[idx] = val;
852 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
853 drvdata->startstop_ctrl |= (1 << (idx + 16));
854 drvdata->enable_ctrl1 |= BIT(25);
855 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700856 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800857}
Pratik Patela9c0e062012-05-28 13:45:35 -0700858static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
859 etm_store_addr_stop);
860
861static ssize_t etm_show_addr_acctype(struct device *dev,
862 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800863{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700864 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800865 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800866
Pratik Patel16aefdb2012-05-30 10:41:23 -0700867 mutex_lock(&drvdata->mutex);
868 val = drvdata->addr_acctype[drvdata->addr_idx];
869 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800870 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
871}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800872
Pratik Patela9c0e062012-05-28 13:45:35 -0700873static ssize_t etm_store_addr_acctype(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 val;
879
880 if (sscanf(buf, "%lx", &val) != 1)
881 return -EINVAL;
882
Pratik Patel16aefdb2012-05-30 10:41:23 -0700883 mutex_lock(&drvdata->mutex);
884 drvdata->addr_acctype[drvdata->addr_idx] = val;
885 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700886 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800887}
Pratik Patela9c0e062012-05-28 13:45:35 -0700888static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
889 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800890
Pratik Patela9c0e062012-05-28 13:45:35 -0700891static ssize_t etm_show_cntr_idx(struct device *dev,
892 struct device_attribute *attr, char *buf)
893{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700894 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700895 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700896
Pratik Patel6630ebe2012-03-06 16:44:22 -0800897 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
898}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800899
Pratik Patela9c0e062012-05-28 13:45:35 -0700900static ssize_t etm_store_cntr_idx(struct device *dev,
901 struct device_attribute *attr,
902 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800903{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700904 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800905 unsigned long val;
906
907 if (sscanf(buf, "%lx", &val) != 1)
908 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700909 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800910 return -EINVAL;
911
912 /* Use mutex to ensure index doesn't change while it gets dereferenced
913 * multiple times within a mutex block elsewhere.
914 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700915 mutex_lock(&drvdata->mutex);
916 drvdata->cntr_idx = val;
917 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700918 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800919}
Pratik Patela9c0e062012-05-28 13:45:35 -0700920static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
921 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800922
Pratik Patela9c0e062012-05-28 13:45:35 -0700923static ssize_t etm_show_cntr_rld_val(struct device *dev,
924 struct device_attribute *attr, char *buf)
925{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700926 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700927 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700928
Pratik Patel16aefdb2012-05-30 10:41:23 -0700929 mutex_lock(&drvdata->mutex);
930 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
931 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700932 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
933}
934
935static ssize_t etm_store_cntr_rld_val(struct device *dev,
936 struct device_attribute *attr,
937 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800938{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700939 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800940 unsigned long val;
941
942 if (sscanf(buf, "%lx", &val) != 1)
943 return -EINVAL;
944
Pratik Patel16aefdb2012-05-30 10:41:23 -0700945 mutex_lock(&drvdata->mutex);
946 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
947 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700948 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800949}
Pratik Patela9c0e062012-05-28 13:45:35 -0700950static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
951 etm_store_cntr_rld_val);
952
953static ssize_t etm_show_cntr_event(struct device *dev,
954 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800955{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700956 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800957 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700958
Pratik Patel16aefdb2012-05-30 10:41:23 -0700959 mutex_lock(&drvdata->mutex);
960 val = drvdata->cntr_event[drvdata->cntr_idx];
961 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800962 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
963}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800964
Pratik Patela9c0e062012-05-28 13:45:35 -0700965static ssize_t etm_store_cntr_event(struct device *dev,
966 struct device_attribute *attr,
967 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800968{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700969 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800970 unsigned long val;
971
972 if (sscanf(buf, "%lx", &val) != 1)
973 return -EINVAL;
974
Pratik Patel16aefdb2012-05-30 10:41:23 -0700975 mutex_lock(&drvdata->mutex);
976 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
977 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700978 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800979}
Pratik Patela9c0e062012-05-28 13:45:35 -0700980static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
981 etm_store_cntr_event);
982
983static ssize_t etm_show_cntr_rld_event(struct device *dev,
984 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800985{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700986 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800987 unsigned long val;
988
Pratik Patel16aefdb2012-05-30 10:41:23 -0700989 mutex_lock(&drvdata->mutex);
990 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
991 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800992 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
993}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800994
Pratik Patela9c0e062012-05-28 13:45:35 -0700995static ssize_t etm_store_cntr_rld_event(struct device *dev,
996 struct device_attribute *attr,
997 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800998{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700999 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001000 unsigned long val;
1001
1002 if (sscanf(buf, "%lx", &val) != 1)
1003 return -EINVAL;
1004
Pratik Patel16aefdb2012-05-30 10:41:23 -07001005 mutex_lock(&drvdata->mutex);
1006 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1007 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001008 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001009}
Pratik Patela9c0e062012-05-28 13:45:35 -07001010static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1011 etm_store_cntr_rld_event);
1012
1013static ssize_t etm_show_cntr_val(struct device *dev,
1014 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001015{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001016 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001017 unsigned long val;
1018
Pratik Patel16aefdb2012-05-30 10:41:23 -07001019 mutex_lock(&drvdata->mutex);
1020 val = drvdata->cntr_val[drvdata->cntr_idx];
1021 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001022 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1023}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001024
Pratik Patela9c0e062012-05-28 13:45:35 -07001025static ssize_t etm_store_cntr_val(struct device *dev,
1026 struct device_attribute *attr,
1027 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001028{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001029 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001030 unsigned long val;
1031
1032 if (sscanf(buf, "%lx", &val) != 1)
1033 return -EINVAL;
1034
Pratik Patel16aefdb2012-05-30 10:41:23 -07001035 mutex_lock(&drvdata->mutex);
1036 drvdata->cntr_val[drvdata->cntr_idx] = val;
1037 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001038 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001039}
Pratik Patela9c0e062012-05-28 13:45:35 -07001040static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1041 etm_store_cntr_val);
1042
1043static ssize_t etm_show_seq_12_event(struct device *dev,
1044 struct device_attribute *attr, char *buf)
1045{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001046 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001047 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001048
Pratik Patela9c0e062012-05-28 13:45:35 -07001049 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1050}
1051
1052static ssize_t etm_store_seq_12_event(struct device *dev,
1053 struct device_attribute *attr,
1054 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001055{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001056 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001057 unsigned long val;
1058
Pratik Patela9c0e062012-05-28 13:45:35 -07001059 if (sscanf(buf, "%lx", &val) != 1)
1060 return -EINVAL;
1061
Pratik Patel16aefdb2012-05-30 10:41:23 -07001062 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001063 return size;
1064}
1065static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1066 etm_store_seq_12_event);
1067
1068static ssize_t etm_show_seq_21_event(struct device *dev,
1069 struct device_attribute *attr, char *buf)
1070{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001071 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001072 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001073
Pratik Patel6630ebe2012-03-06 16:44:22 -08001074 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1075}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001076
Pratik Patela9c0e062012-05-28 13:45:35 -07001077static ssize_t etm_store_seq_21_event(struct device *dev,
1078 struct device_attribute *attr,
1079 const char *buf, size_t size)
1080{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001081 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001082 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001083
Pratik Patela9c0e062012-05-28 13:45:35 -07001084 if (sscanf(buf, "%lx", &val) != 1)
1085 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001086
Pratik Patel16aefdb2012-05-30 10:41:23 -07001087 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001088 return size;
1089}
1090static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1091 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001092
Pratik Patela9c0e062012-05-28 13:45:35 -07001093static ssize_t etm_show_seq_23_event(struct device *dev,
1094 struct device_attribute *attr, char *buf)
1095{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001096 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001097 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001098
Pratik Patela9c0e062012-05-28 13:45:35 -07001099 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1100}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001101
Pratik Patela9c0e062012-05-28 13:45:35 -07001102static ssize_t etm_store_seq_23_event(struct device *dev,
1103 struct device_attribute *attr,
1104 const char *buf, size_t size)
1105{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001106 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001107 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001108
Pratik Patela9c0e062012-05-28 13:45:35 -07001109 if (sscanf(buf, "%lx", &val) != 1)
1110 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001111
Pratik Patel16aefdb2012-05-30 10:41:23 -07001112 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001113 return size;
1114}
1115static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1116 etm_store_seq_23_event);
1117
1118static ssize_t etm_show_seq_31_event(struct device *dev,
1119 struct device_attribute *attr, char *buf)
1120{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001121 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001122 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001123
Pratik Patela9c0e062012-05-28 13:45:35 -07001124 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1125}
1126
1127static ssize_t etm_store_seq_31_event(struct device *dev,
1128 struct device_attribute *attr,
1129 const char *buf, size_t size)
1130{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001131 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001132 unsigned long val;
1133
1134 if (sscanf(buf, "%lx", &val) != 1)
1135 return -EINVAL;
1136
Pratik Patel16aefdb2012-05-30 10:41:23 -07001137 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001138 return size;
1139}
1140static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1141 etm_store_seq_31_event);
1142
1143static ssize_t etm_show_seq_32_event(struct device *dev,
1144 struct device_attribute *attr, char *buf)
1145{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001146 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001147 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001148
Pratik Patela9c0e062012-05-28 13:45:35 -07001149 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1150}
1151
1152static ssize_t etm_store_seq_32_event(struct device *dev,
1153 struct device_attribute *attr,
1154 const char *buf, size_t size)
1155{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001156 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001157 unsigned long val;
1158
1159 if (sscanf(buf, "%lx", &val) != 1)
1160 return -EINVAL;
1161
Pratik Patel16aefdb2012-05-30 10:41:23 -07001162 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001163 return size;
1164}
1165static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1166 etm_store_seq_32_event);
1167
1168static ssize_t etm_show_seq_13_event(struct device *dev,
1169 struct device_attribute *attr, char *buf)
1170{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001171 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001172 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001173
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{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001181 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001182 unsigned long val;
1183
1184 if (sscanf(buf, "%lx", &val) != 1)
1185 return -EINVAL;
1186
Pratik Patel16aefdb2012-05-30 10:41:23 -07001187 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001188 return size;
1189}
1190static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1191 etm_store_seq_13_event);
1192
1193static ssize_t etm_show_seq_curr_state(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_curr_state;
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_curr_state(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
1209 if (sscanf(buf, "%lx", &val) != 1)
1210 return -EINVAL;
1211 if (val > ETM_SEQ_STATE_MAX_VAL)
1212 return -EINVAL;
1213
Pratik Patel16aefdb2012-05-30 10:41:23 -07001214 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001215 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001216}
Pratik Patela9c0e062012-05-28 13:45:35 -07001217static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1218 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001219
Pratik Patela9c0e062012-05-28 13:45:35 -07001220static ssize_t etm_show_ctxid_idx(struct device *dev,
1221 struct device_attribute *attr, char *buf)
1222{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001223 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001224 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001225
Pratik Patela9c0e062012-05-28 13:45:35 -07001226 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1227}
1228
1229static ssize_t etm_store_ctxid_idx(struct device *dev,
1230 struct device_attribute *attr,
1231 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001232{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001233 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001234 unsigned long val;
1235
1236 if (sscanf(buf, "%lx", &val) != 1)
1237 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001238 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001239 return -EINVAL;
1240
1241 /* Use mutex to ensure index doesn't change while it gets dereferenced
1242 * multiple times within a mutex block elsewhere.
1243 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001244 mutex_lock(&drvdata->mutex);
1245 drvdata->ctxid_idx = val;
1246 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001247 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001248}
Pratik Patela9c0e062012-05-28 13:45:35 -07001249static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1250 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001251
Pratik Patela9c0e062012-05-28 13:45:35 -07001252static ssize_t etm_show_ctxid_val(struct device *dev,
1253 struct device_attribute *attr, char *buf)
1254{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001255 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001256 unsigned long val;
1257
Pratik Patel16aefdb2012-05-30 10:41:23 -07001258 mutex_lock(&drvdata->mutex);
1259 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1260 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001261 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1262}
1263
1264static ssize_t etm_store_ctxid_val(struct device *dev,
1265 struct device_attribute *attr,
1266 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001267{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001268 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001269 unsigned long val;
1270
1271 if (sscanf(buf, "%lx", &val) != 1)
1272 return -EINVAL;
1273
Pratik Patel16aefdb2012-05-30 10:41:23 -07001274 mutex_lock(&drvdata->mutex);
1275 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1276 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001277 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001278}
Pratik Patela9c0e062012-05-28 13:45:35 -07001279static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1280 etm_store_ctxid_val);
1281
1282static ssize_t etm_show_ctxid_mask(struct device *dev,
1283 struct device_attribute *attr, char *buf)
1284{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001285 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001286 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001287
Pratik Patela9c0e062012-05-28 13:45:35 -07001288 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1289}
1290
1291static ssize_t etm_store_ctxid_mask(struct device *dev,
1292 struct device_attribute *attr,
1293 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001294{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001295 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001296 unsigned long val;
1297
Pratik Patela9c0e062012-05-28 13:45:35 -07001298 if (sscanf(buf, "%lx", &val) != 1)
1299 return -EINVAL;
1300
Pratik Patel16aefdb2012-05-30 10:41:23 -07001301 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001302 return size;
1303}
1304static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1305 etm_store_ctxid_mask);
1306
1307static ssize_t etm_show_sync_freq(struct device *dev,
1308 struct device_attribute *attr, char *buf)
1309{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001310 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001311 unsigned long val = drvdata->sync_freq;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001312 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1313}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001314
Pratik Patela9c0e062012-05-28 13:45:35 -07001315static ssize_t etm_store_sync_freq(struct device *dev,
1316 struct device_attribute *attr,
1317 const char *buf, size_t size)
1318{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001319 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001320 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001321
Pratik Patela9c0e062012-05-28 13:45:35 -07001322 if (sscanf(buf, "%lx", &val) != 1)
1323 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001324
Pratik Patel16aefdb2012-05-30 10:41:23 -07001325 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001326 return size;
1327}
1328static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1329 etm_store_sync_freq);
1330
1331static ssize_t etm_show_timestamp_event(struct device *dev,
1332 struct device_attribute *attr,
1333 char *buf)
1334{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001335 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001336 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001337
Pratik Patela9c0e062012-05-28 13:45:35 -07001338 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1339}
1340
1341static ssize_t etm_store_timestamp_event(struct device *dev,
1342 struct device_attribute *attr,
1343 const char *buf, size_t size)
1344{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001345 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001346 unsigned long val;
1347
1348 if (sscanf(buf, "%lx", &val) != 1)
1349 return -EINVAL;
1350
Pratik Patel16aefdb2012-05-30 10:41:23 -07001351 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001352 return size;
1353}
1354static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1355 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001356
1357static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001358 &dev_attr_nr_addr_cmp.attr,
1359 &dev_attr_nr_cntr.attr,
1360 &dev_attr_nr_ctxid_cmp.attr,
1361 &dev_attr_reset.attr,
1362 &dev_attr_mode.attr,
1363 &dev_attr_trigger_event.attr,
1364 &dev_attr_enable_event.attr,
1365 &dev_attr_fifofull_level.attr,
1366 &dev_attr_addr_idx.attr,
1367 &dev_attr_addr_single.attr,
1368 &dev_attr_addr_range.attr,
1369 &dev_attr_addr_start.attr,
1370 &dev_attr_addr_stop.attr,
1371 &dev_attr_addr_acctype.attr,
1372 &dev_attr_cntr_idx.attr,
1373 &dev_attr_cntr_rld_val.attr,
1374 &dev_attr_cntr_event.attr,
1375 &dev_attr_cntr_rld_event.attr,
1376 &dev_attr_cntr_val.attr,
1377 &dev_attr_seq_12_event.attr,
1378 &dev_attr_seq_21_event.attr,
1379 &dev_attr_seq_23_event.attr,
1380 &dev_attr_seq_31_event.attr,
1381 &dev_attr_seq_32_event.attr,
1382 &dev_attr_seq_13_event.attr,
1383 &dev_attr_seq_curr_state.attr,
1384 &dev_attr_ctxid_idx.attr,
1385 &dev_attr_ctxid_val.attr,
1386 &dev_attr_ctxid_mask.attr,
1387 &dev_attr_sync_freq.attr,
1388 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001389 NULL,
1390};
1391
1392static struct attribute_group etm_attr_grp = {
1393 .attrs = etm_attrs,
1394};
1395
Pratik Patel3b0ca882012-06-01 16:54:14 -07001396static const struct attribute_group *etm_attr_grps[] = {
1397 &etm_attr_grp,
1398 NULL,
1399};
1400
1401/* Memory mapped writes to clear os lock not supported */
1402static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001403{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001404 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001405
Pratik Patel3b0ca882012-06-01 16:54:14 -07001406 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1407 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001408}
1409
Stephen Boyda9510502012-04-24 16:23:34 -07001410static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001411{
Pratik Patel61de7302012-03-07 12:06:10 -08001412 switch (arch) {
1413 case PFT_ARCH_V1_1:
1414 break;
1415 default:
1416 return false;
1417 }
1418 return true;
1419}
1420
Pratik Patel3b0ca882012-06-01 16:54:14 -07001421static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
Pratik Patel61de7302012-03-07 12:06:10 -08001422{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001423 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -08001424 uint32_t etmidr;
1425 uint32_t etmccr;
Pratik Patel7831c082011-06-08 21:44:37 -07001426
Pratik Patel17f3b822011-11-21 12:41:47 -08001427 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel492b3012012-03-06 14:22:30 -08001428 etm_os_unlock(NULL);
1429 smp_call_function(etm_os_unlock, NULL, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001430 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001431 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001432 etm_clr_pwrdwn(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001433 /* Set prog bit. It will be set from reset but this is included to
1434 * ensure it is set
1435 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001436 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001437
1438 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001439 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001440 drvdata->arch = BMVAL(etmidr, 4, 11);
1441 if (etm_arch_supported(drvdata->arch) == false) {
Pratik Patel61de7302012-03-07 12:06:10 -08001442 ret = -EINVAL;
1443 goto err;
1444 }
Pratik Patel7831c082011-06-08 21:44:37 -07001445
Pratik Patel3b0ca882012-06-01 16:54:14 -07001446 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001447 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1448 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1449 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1450 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1451 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001452
Pratik Patel17f3b822011-11-21 12:41:47 -08001453 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001454 etm_set_pwrdwn(drvdata);
1455 ETM_LOCK(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001456
1457 return 0;
1458err:
1459 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001460}
1461
Pratik Patel3b0ca882012-06-01 16:54:14 -07001462static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001463{
1464 int i;
1465
1466 drvdata->trigger_event = 0x406F;
1467 drvdata->enable_event = 0x6F;
1468 drvdata->enable_ctrl1 = 0x1;
1469 drvdata->fifofull_level = 0x28;
1470 if (drvdata->nr_addr_cmp >= 2) {
1471 drvdata->addr_val[0] = (uint32_t) _stext;
1472 drvdata->addr_val[1] = (uint32_t) _etext;
1473 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1474 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1475 }
1476 for (i = 0; i < drvdata->nr_cntr; i++) {
1477 drvdata->cntr_event[i] = 0x406F;
1478 drvdata->cntr_rld_event[i] = 0x406F;
1479 }
1480 drvdata->seq_12_event = 0x406F;
1481 drvdata->seq_21_event = 0x406F;
1482 drvdata->seq_23_event = 0x406F;
1483 drvdata->seq_31_event = 0x406F;
1484 drvdata->seq_32_event = 0x406F;
1485 drvdata->seq_13_event = 0x406F;
1486 drvdata->sync_freq = 0x80;
1487 drvdata->timestamp_event = 0x406F;
1488
1489 /* Overrides for Krait pass1 */
1490 if (cpu_is_krait_v1()) {
1491 /* Krait pass1 doesn't support include filtering and non-cycle
1492 * accurate tracing
1493 */
1494 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1495 drvdata->ctrl = 0x1000;
1496 drvdata->enable_ctrl1 = 0x1000000;
1497 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1498 drvdata->addr_val[i] = 0x0;
1499 drvdata->addr_acctype[i] = 0x0;
1500 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1501 }
1502 }
1503}
1504
Pratik Patel492b3012012-03-06 14:22:30 -08001505static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001506{
Pratik Patele5771792011-09-17 18:33:54 -07001507 int ret;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001508 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001509 struct resource *res;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001510 static int etm_count;
1511 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001512
Pratik Patel16aefdb2012-05-30 10:41:23 -07001513 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
1514 if (!drvdata) {
1515 ret = -ENOMEM;
1516 goto err_kzalloc_drvdata;
1517 }
Pratik Patel7831c082011-06-08 21:44:37 -07001518 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1519 if (!res) {
1520 ret = -EINVAL;
1521 goto err_res;
1522 }
Pratik Patel16aefdb2012-05-30 10:41:23 -07001523 drvdata->base = ioremap_nocache(res->start, resource_size(res));
1524 if (!drvdata->base) {
Pratik Patel7831c082011-06-08 21:44:37 -07001525 ret = -EINVAL;
1526 goto err_ioremap;
1527 }
Pratik Patel16aefdb2012-05-30 10:41:23 -07001528 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001529 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001530
Pratik Patel16aefdb2012-05-30 10:41:23 -07001531 mutex_init(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001532 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001533 pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
1534 PM_QOS_DEFAULT_VALUE);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001535 drvdata->cpu = etm_count++;
Pratik Patele10a77c2012-03-20 10:35:16 -07001536
Pratik Patel16aefdb2012-05-30 10:41:23 -07001537 drvdata->clk = clk_get(drvdata->dev, "core_clk");
1538 if (IS_ERR(drvdata->clk)) {
1539 ret = PTR_ERR(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001540 goto err_clk_get;
1541 }
1542
Pratik Patel6fb38342012-06-03 14:51:38 -07001543 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001544 if (ret)
Pratik Patelf17b1472012-05-25 22:23:52 -07001545 goto err_clk_rate;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001546 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001547 if (ret)
1548 goto err_clk_enable;
Pratik Patel7831c082011-06-08 21:44:37 -07001549
Pratik Patel3b0ca882012-06-01 16:54:14 -07001550 ret = etm_init_arch_data(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001551 if (ret)
1552 goto err_arch;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001553 etm_init_default_data(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001554
Pratik Patel16aefdb2012-05-30 10:41:23 -07001555 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001556
Pratik Patel3b0ca882012-06-01 16:54:14 -07001557 desc = kzalloc(sizeof(*desc), GFP_KERNEL);
1558 if (!desc) {
1559 ret = -ENOMEM;
1560 goto err_kzalloc_desc;
1561 }
1562 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1563 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1564 desc->ops = &etm_cs_ops;
1565 desc->pdata = pdev->dev.platform_data;
1566 desc->dev = &pdev->dev;
1567 desc->groups = etm_attr_grps;
1568 desc->owner = THIS_MODULE;
1569 drvdata->csdev = coresight_register(desc);
1570 if (IS_ERR(drvdata->csdev)) {
1571 ret = PTR_ERR(drvdata->csdev);
1572 goto err_coresight_register;
1573 }
1574 kfree(desc);
1575
Pratik Patel16aefdb2012-05-30 10:41:23 -07001576 dev_info(drvdata->dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001577
Pratik Patel3b0ca882012-06-01 16:54:14 -07001578 if (boot_enable)
1579 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001580
1581 return 0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001582err_coresight_register:
1583 kfree(desc);
1584err_kzalloc_desc:
Pratik Patel61de7302012-03-07 12:06:10 -08001585err_arch:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001586 clk_disable_unprepare(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001587err_clk_enable:
1588err_clk_rate:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001589 clk_put(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001590err_clk_get:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001591 pm_qos_remove_request(&drvdata->qos_req);
1592 wake_lock_destroy(&drvdata->wake_lock);
1593 mutex_destroy(&drvdata->mutex);
1594 iounmap(drvdata->base);
Pratik Patel7831c082011-06-08 21:44:37 -07001595err_ioremap:
1596err_res:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001597 kfree(drvdata);
1598err_kzalloc_drvdata:
1599 dev_err(drvdata->dev, "ETM init failed\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001600 return ret;
1601}
1602
Pratik Patelf6fe9182012-03-20 14:04:18 -07001603static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001604{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001605 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1606
1607 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001608 clk_put(drvdata->clk);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001609 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 return 0;
1615}
1616
Pratik Patel9eae4822012-05-14 17:34:53 -07001617static struct of_device_id etm_match[] = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001618 {.compatible = "coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001619 {}
1620};
1621
Pratik Patel492b3012012-03-06 14:22:30 -08001622static struct platform_driver etm_driver = {
1623 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001624 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001625 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001626 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001627 .owner = THIS_MODULE,
1628 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001629 },
1630};
1631
Pratik Patel492b3012012-03-06 14:22:30 -08001632int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001633{
Pratik Patel492b3012012-03-06 14:22:30 -08001634 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001635}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001636module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001637
Pratik Patelf6fe9182012-03-20 14:04:18 -07001638void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001639{
Pratik Patel492b3012012-03-06 14:22:30 -08001640 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001641}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001642module_exit(etm_exit);
1643
1644MODULE_LICENSE("GPL v2");
1645MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");