blob: 8fed9260d4fc779c2083a84fc5697ab492a4a03e [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 Patel5f6d1af2012-06-13 15:48:13 -070031#include <linux/of_coresight.h>
Pratik Patel1746b8f2012-06-02 21:11:41 -070032#include <linux/coresight.h>
Pratik Pateld30deda2012-02-01 14:40:55 -080033#include <asm/sections.h>
Pratik Patel2d0c7b62012-02-24 19:04:37 -080034#include <mach/socinfo.h>
Pratik Patel7831c082011-06-08 21:44:37 -070035
Pratik Patel1746b8f2012-06-02 21:11:41 -070036#include "coresight-priv.h"
Pratik Patel7831c082011-06-08 21:44:37 -070037
Pratik Patel3b0ca882012-06-01 16:54:14 -070038#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 * Device registers:
56 * 0x000 - 0x2FC: Trace registers
57 * 0x300 - 0x314: Management registers
58 * 0x318 - 0xEFC: Trace registers
59 *
60 * Coresight registers
61 * 0xF00 - 0xF9C: Management registers
62 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
63 * Trace registers in PFTv1.1
64 * 0xFA8 - 0xFFC: Management registers
65 */
66
67/* Trace registers (0x000-0x2FC) */
68#define ETMCR (0x000)
69#define ETMCCR (0x004)
70#define ETMTRIGGER (0x008)
71#define ETMSR (0x010)
72#define ETMSCR (0x014)
73#define ETMTSSCR (0x018)
74#define ETMTEEVR (0x020)
75#define ETMTECR1 (0x024)
76#define ETMFFLR (0x02C)
77#define ETMACVRn(n) (0x040 + (n * 4))
78#define ETMACTRn(n) (0x080 + (n * 4))
79#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
80#define ETMCNTENRn(n) (0x150 + (n * 4))
81#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
82#define ETMCNTVRn(n) (0x170 + (n * 4))
83#define ETMSQ12EVR (0x180)
84#define ETMSQ21EVR (0x184)
85#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -080086#define ETMSQ31EVR (0x18C)
87#define ETMSQ32EVR (0x190)
88#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -070089#define ETMSQR (0x19C)
90#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
91#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
92#define ETMCIDCMR (0x1BC)
93#define ETMIMPSPEC0 (0x1C0)
94#define ETMIMPSPEC1 (0x1C4)
95#define ETMIMPSPEC2 (0x1C8)
96#define ETMIMPSPEC3 (0x1CC)
97#define ETMIMPSPEC4 (0x1D0)
98#define ETMIMPSPEC5 (0x1D4)
99#define ETMIMPSPEC6 (0x1D8)
100#define ETMIMPSPEC7 (0x1DC)
101#define ETMSYNCFR (0x1E0)
102#define ETMIDR (0x1E4)
103#define ETMCCER (0x1E8)
104#define ETMEXTINSELR (0x1EC)
105#define ETMTESSEICR (0x1F0)
106#define ETMEIBCR (0x1F4)
107#define ETMTSEVR (0x1F8)
108#define ETMAUXCR (0x1FC)
109#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800110#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700111/* Management registers (0x300-0x314) */
112#define ETMOSLAR (0x300)
113#define ETMOSLSR (0x304)
114#define ETMOSSRR (0x308)
115#define ETMPDCR (0x310)
116#define ETMPDSR (0x314)
117
Pratik Patel61de7302012-03-07 12:06:10 -0800118#define ETM_MAX_ADDR_CMP (16)
119#define ETM_MAX_CNTR (4)
120#define ETM_MAX_CTXID_CMP (3)
121
Pratik Patel6630ebe2012-03-06 16:44:22 -0800122#define ETM_MODE_EXCLUDE BIT(0)
123#define ETM_MODE_CYCACC BIT(1)
124#define ETM_MODE_STALL BIT(2)
125#define ETM_MODE_TIMESTAMP BIT(3)
126#define ETM_MODE_CTXID BIT(4)
127#define ETM_MODE_ALL (0x1F)
128
129#define ETM_EVENT_MASK (0x1FFFF)
130#define ETM_SYNC_MASK (0xFFF)
131#define ETM_ALL_MASK (0xFFFFFFFF)
132
133#define ETM_SEQ_STATE_MAX_VAL (0x2)
134
Pratik Patel3b0ca882012-06-01 16:54:14 -0700135enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800136 ETM_ADDR_TYPE_NONE,
137 ETM_ADDR_TYPE_SINGLE,
138 ETM_ADDR_TYPE_RANGE,
139 ETM_ADDR_TYPE_START,
140 ETM_ADDR_TYPE_STOP,
141};
142
Pratik Patel29cba152012-01-03 11:40:26 -0800143#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700144static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800145#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700146static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800147#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700148module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700149 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700150);
151
Pratik Patel16aefdb2012-05-30 10:41:23 -0700152struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700153 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700154 struct device *dev;
155 struct coresight_device *csdev;
156 struct clk *clk;
157 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700158 struct wake_lock wake_lock;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700159 struct pm_qos_request qos_req;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700160 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800161 uint8_t arch;
162 uint8_t nr_addr_cmp;
163 uint8_t nr_cntr;
164 uint8_t nr_ext_inp;
165 uint8_t nr_ext_out;
166 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800167 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800168 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800169 uint32_t ctrl;
170 uint32_t trigger_event;
171 uint32_t startstop_ctrl;
172 uint32_t enable_event;
173 uint32_t enable_ctrl1;
174 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800175 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800176 uint32_t addr_val[ETM_MAX_ADDR_CMP];
177 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800178 uint32_t addr_type[ETM_MAX_ADDR_CMP];
179 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800180 uint32_t cntr_rld_val[ETM_MAX_CNTR];
181 uint32_t cntr_event[ETM_MAX_CNTR];
182 uint32_t cntr_rld_event[ETM_MAX_CNTR];
183 uint32_t cntr_val[ETM_MAX_CNTR];
184 uint32_t seq_12_event;
185 uint32_t seq_21_event;
186 uint32_t seq_23_event;
187 uint32_t seq_31_event;
188 uint32_t seq_32_event;
189 uint32_t seq_13_event;
190 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800191 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800192 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
193 uint32_t ctxid_mask;
194 uint32_t sync_freq;
195 uint32_t timestamp_event;
Pratik Patel7831c082011-06-08 21:44:37 -0700196};
197
Pratik Patelc14b4df2012-09-05 18:07:59 -0700198static struct etm_drvdata *etm0drvdata;
199
Pratik Patel17f3b822011-11-21 12:41:47 -0800200/* ETM clock is derived from the processor clock and gets enabled on a
201 * logical OR of below items on Krait (pass2 onwards):
202 * 1.CPMR[ETMCLKEN] is 1
203 * 2.ETMCR[PD] is 0
204 * 3.ETMPDCR[PU] is 1
205 * 4.Reset is asserted (core or debug)
206 * 5.APB memory mapped requests (eg. EDAP access)
207 *
208 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
209 * enables
210 *
211 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
212 * clock vote in the driver and the save-restore code uses 1. above
213 * for its vote
214 */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700215static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700216{
217 uint32_t etmcr;
218
Pratik Patel3b0ca882012-06-01 16:54:14 -0700219 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700220 etmcr |= BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700221 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700222}
223
Pratik Patel3b0ca882012-06-01 16:54:14 -0700224static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700225{
226 uint32_t etmcr;
227
Pratik Patel3b0ca882012-06-01 16:54:14 -0700228 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700229 etmcr &= ~BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700230 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700231}
232
Pratik Patel3b0ca882012-06-01 16:54:14 -0700233static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700234{
235 uint32_t etmcr;
236 int count;
237
Pratik Patel3b0ca882012-06-01 16:54:14 -0700238 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700239 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700240 etm_writel(drvdata, etmcr, ETMCR);
241 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700242 && count > 0; count--)
243 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800244 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700245 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700246}
247
Pratik Patel3b0ca882012-06-01 16:54:14 -0700248static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700249{
250 uint32_t etmcr;
251 int count;
252
Pratik Patel3b0ca882012-06-01 16:54:14 -0700253 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700254 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700255 etm_writel(drvdata, etmcr, ETMCR);
256 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700257 && count > 0; count--)
258 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800259 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700260 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700261}
262
Pratik Patel3b0ca882012-06-01 16:54:14 -0700263static void __etm_enable(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700264{
Pratik Patel17f3b822011-11-21 12:41:47 -0800265 int i;
Pratik Patel7831c082011-06-08 21:44:37 -0700266
Pratik Patel3b0ca882012-06-01 16:54:14 -0700267 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800268 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700269 etm_clr_pwrdwn(drvdata);
270 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700271
Pratik Patel3b0ca882012-06-01 16:54:14 -0700272 etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
273 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
274 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
275 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
276 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
277 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700278 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700279 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
280 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700281 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700282 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700283 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
284 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
285 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700286 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700287 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800288 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700289 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
290 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
291 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
292 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
293 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
294 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
295 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700296 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700297 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700298 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700299 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
300 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
301 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
302 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
303 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
304 etm_writel(drvdata, 0x00000000, ETMAUXCR);
305 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
306 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800307
Pratik Patel3b0ca882012-06-01 16:54:14 -0700308 etm_clr_prog(drvdata);
309 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700310}
311
Pratik Patel3b0ca882012-06-01 16:54:14 -0700312static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700313{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700314 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
315 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800316
Pratik Patel16aefdb2012-05-30 10:41:23 -0700317 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700318 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700319 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700320 *
321 * we rely on the user to prevent hotplug on/off racing with this
322 * operation and to ensure cores where trace is expected to be turned
323 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700324 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700325 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700326
Pratik Patel16aefdb2012-05-30 10:41:23 -0700327 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700328 if (ret)
329 goto err_clk;
330
Pratik Patel3b0ca882012-06-01 16:54:14 -0700331 mutex_lock(&drvdata->mutex);
332 __etm_enable(drvdata);
333 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700334
Pratik Patel16aefdb2012-05-30 10:41:23 -0700335 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
336 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700337
Pratik Patel16aefdb2012-05-30 10:41:23 -0700338 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700339 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700340err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700341 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
342 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800343 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700344}
345
Pratik Patel3b0ca882012-06-01 16:54:14 -0700346static void __etm_disable(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700347{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700348 ETM_UNLOCK(drvdata);
349 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700350
Pratik Patel17f3b822011-11-21 12:41:47 -0800351 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700352 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700353
Pratik Patel17f3b822011-11-21 12:41:47 -0800354 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700355 etm_set_pwrdwn(drvdata);
356 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700357}
358
Pratik Patel3b0ca882012-06-01 16:54:14 -0700359static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700360{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700361 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800362
Pratik Patel16aefdb2012-05-30 10:41:23 -0700363 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700364 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700365 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700366 *
367 * we rely on the user to prevent hotplug on/off racing with this
368 * operation and to ensure cores where trace is expected to be turned
369 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700370 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700371 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700372
Pratik Patel3b0ca882012-06-01 16:54:14 -0700373 mutex_lock(&drvdata->mutex);
374 __etm_disable(drvdata);
375 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700376
Pratik Patel16aefdb2012-05-30 10:41:23 -0700377 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700378
Pratik Patel16aefdb2012-05-30 10:41:23 -0700379 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
380 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700381
Pratik Patel16aefdb2012-05-30 10:41:23 -0700382 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700383}
384
Pratik Patel3b0ca882012-06-01 16:54:14 -0700385static const struct coresight_ops_source etm_source_ops = {
386 .enable = etm_enable,
387 .disable = etm_disable,
388};
Pratik Patel17f3b822011-11-21 12:41:47 -0800389
Pratik Patel3b0ca882012-06-01 16:54:14 -0700390static const struct coresight_ops etm_cs_ops = {
391 .source_ops = &etm_source_ops,
392};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800393
Pratik Patela9c0e062012-05-28 13:45:35 -0700394static ssize_t etm_show_nr_addr_cmp(struct device *dev,
395 struct device_attribute *attr, char *buf)
396{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700397 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700398 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700399
Pratik Patela9c0e062012-05-28 13:45:35 -0700400 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
401}
402static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
403
404static ssize_t etm_show_nr_cntr(struct device *dev,
405 struct device_attribute *attr, char *buf)
406{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700407 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700408 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700409
Pratik Patela9c0e062012-05-28 13:45:35 -0700410 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
411}
412static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
413
414static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
415 struct device_attribute *attr, char *buf)
416{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700417 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700418 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700419
Pratik Patela9c0e062012-05-28 13:45:35 -0700420 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
421}
422static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
423
424static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
425 char *buf)
426{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700427 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700428 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700429
Pratik Patela9c0e062012-05-28 13:45:35 -0700430 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
431}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800432
Pratik Pateld30deda2012-02-01 14:40:55 -0800433/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700434static ssize_t etm_store_reset(struct device *dev,
435 struct device_attribute *attr, const char *buf,
436 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800437{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700438 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800439 int i;
440 unsigned long val;
441
442 if (sscanf(buf, "%lx", &val) != 1)
443 return -EINVAL;
444
Pratik Patel16aefdb2012-05-30 10:41:23 -0700445 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800446 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700447 drvdata->mode = ETM_MODE_EXCLUDE;
448 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800449 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700450 drvdata->mode |= ETM_MODE_CYCACC;
451 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800452 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700453 drvdata->trigger_event = 0x406F;
454 drvdata->startstop_ctrl = 0x0;
455 drvdata->enable_event = 0x6F;
456 drvdata->enable_ctrl1 = 0x1000000;
457 drvdata->fifofull_level = 0x28;
458 drvdata->addr_idx = 0x0;
459 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
460 drvdata->addr_val[i] = 0x0;
461 drvdata->addr_acctype[i] = 0x0;
462 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800463 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700464 drvdata->cntr_idx = 0x0;
465 for (i = 0; i < drvdata->nr_cntr; i++) {
466 drvdata->cntr_rld_val[i] = 0x0;
467 drvdata->cntr_event[i] = 0x406F;
468 drvdata->cntr_rld_event[i] = 0x406F;
469 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800470 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700471 drvdata->seq_12_event = 0x406F;
472 drvdata->seq_21_event = 0x406F;
473 drvdata->seq_23_event = 0x406F;
474 drvdata->seq_31_event = 0x406F;
475 drvdata->seq_32_event = 0x406F;
476 drvdata->seq_13_event = 0x406F;
477 drvdata->seq_curr_state = 0x0;
478 drvdata->ctxid_idx = 0x0;
479 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
480 drvdata->ctxid_val[i] = 0x0;
481 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700482 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
483 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
484 drvdata->sync_freq = 0x100;
485 else
486 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700487 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800488 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700489 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700490 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800491}
Pratik Patela9c0e062012-05-28 13:45:35 -0700492static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800493
Pratik Patela9c0e062012-05-28 13:45:35 -0700494static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
495 char *buf)
496{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700497 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700498 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700499
Pratik Patela9c0e062012-05-28 13:45:35 -0700500 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
501}
502
503static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
504 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800505{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700506 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800507 unsigned long val;
508
509 if (sscanf(buf, "%lx", &val) != 1)
510 return -EINVAL;
511
Pratik Patel16aefdb2012-05-30 10:41:23 -0700512 mutex_lock(&drvdata->mutex);
513 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800514
Pratik Patel16aefdb2012-05-30 10:41:23 -0700515 if (drvdata->mode & ETM_MODE_EXCLUDE)
516 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800517 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700518 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800519
Pratik Patel16aefdb2012-05-30 10:41:23 -0700520 if (drvdata->mode & ETM_MODE_CYCACC)
521 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800522 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700523 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800524
Pratik Patel16aefdb2012-05-30 10:41:23 -0700525 if (drvdata->mode & ETM_MODE_STALL)
526 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800527 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700528 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800529
Pratik Patel16aefdb2012-05-30 10:41:23 -0700530 if (drvdata->mode & ETM_MODE_TIMESTAMP)
531 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800532 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700533 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700534
Pratik Patel16aefdb2012-05-30 10:41:23 -0700535 if (drvdata->mode & ETM_MODE_CTXID)
536 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800537 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700538 drvdata->ctrl &= ~(BIT(14) | BIT(15));
539 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800540
Pratik Patela9c0e062012-05-28 13:45:35 -0700541 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800542}
Pratik Patela9c0e062012-05-28 13:45:35 -0700543static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800544
Pratik Patela9c0e062012-05-28 13:45:35 -0700545static ssize_t etm_show_trigger_event(struct device *dev,
546 struct device_attribute *attr, char *buf)
547{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700548 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700549 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700550
Pratik Patela9c0e062012-05-28 13:45:35 -0700551 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
552}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800553
Pratik Patela9c0e062012-05-28 13:45:35 -0700554static ssize_t etm_store_trigger_event(struct device *dev,
555 struct device_attribute *attr,
556 const char *buf, size_t size)
557{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700558 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700559 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800560
Pratik Patela9c0e062012-05-28 13:45:35 -0700561 if (sscanf(buf, "%lx", &val) != 1)
562 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800563
Pratik Patel16aefdb2012-05-30 10:41:23 -0700564 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700565 return size;
566}
567static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
568 etm_store_trigger_event);
569
570static ssize_t etm_show_enable_event(struct device *dev,
571 struct device_attribute *attr, char *buf)
572{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700573 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700574 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700575
Pratik Patela9c0e062012-05-28 13:45:35 -0700576 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
577}
578
579static ssize_t etm_store_enable_event(struct device *dev,
580 struct device_attribute *attr,
581 const char *buf, size_t size)
582{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700583 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700584 unsigned long val;
585
586 if (sscanf(buf, "%lx", &val) != 1)
587 return -EINVAL;
588
Pratik Patel16aefdb2012-05-30 10:41:23 -0700589 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700590 return size;
591}
592static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
593 etm_store_enable_event);
594
595static ssize_t etm_show_fifofull_level(struct device *dev,
596 struct device_attribute *attr, char *buf)
597{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700598 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700599 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700600
Pratik Patela9c0e062012-05-28 13:45:35 -0700601 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
602}
603
604static ssize_t etm_store_fifofull_level(struct device *dev,
605 struct device_attribute *attr,
606 const char *buf, size_t size)
607{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700608 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700609 unsigned long val;
610
611 if (sscanf(buf, "%lx", &val) != 1)
612 return -EINVAL;
613
Pratik Patel16aefdb2012-05-30 10:41:23 -0700614 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700615 return size;
616}
617static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
618 etm_store_fifofull_level);
619
620static ssize_t etm_show_addr_idx(struct device *dev,
621 struct device_attribute *attr, char *buf)
622{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700623 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700624 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700625
Pratik Patela9c0e062012-05-28 13:45:35 -0700626 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
627}
628
629static ssize_t etm_store_addr_idx(struct device *dev,
630 struct device_attribute *attr,
631 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800632{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700633 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800634 unsigned long val;
635
636 if (sscanf(buf, "%lx", &val) != 1)
637 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700638 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800639 return -EINVAL;
640
641 /* Use mutex to ensure index doesn't change while it gets dereferenced
642 * multiple times within a mutex block elsewhere.
643 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700644 mutex_lock(&drvdata->mutex);
645 drvdata->addr_idx = val;
646 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700647 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800648}
Pratik Patela9c0e062012-05-28 13:45:35 -0700649static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
650 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800651
Pratik Patela9c0e062012-05-28 13:45:35 -0700652static ssize_t etm_show_addr_single(struct device *dev,
653 struct device_attribute *attr, char *buf)
654{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700655 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700656 unsigned long val;
657 uint8_t idx;
658
Pratik Patel16aefdb2012-05-30 10:41:23 -0700659 mutex_lock(&drvdata->mutex);
660 idx = drvdata->addr_idx;
661 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
662 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
663 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700664 return -EPERM;
665 }
666
Pratik Patel16aefdb2012-05-30 10:41:23 -0700667 val = drvdata->addr_val[idx];
668 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700669 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
670}
671
672static ssize_t etm_store_addr_single(struct device *dev,
673 struct device_attribute *attr,
674 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800675{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700676 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800677 unsigned long val;
678 uint8_t idx;
679
680 if (sscanf(buf, "%lx", &val) != 1)
681 return -EINVAL;
682
Pratik Patel16aefdb2012-05-30 10:41:23 -0700683 mutex_lock(&drvdata->mutex);
684 idx = drvdata->addr_idx;
685 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
686 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
687 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800688 return -EPERM;
689 }
690
Pratik Patel16aefdb2012-05-30 10:41:23 -0700691 drvdata->addr_val[idx] = val;
692 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
693 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700694 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800695}
Pratik Patela9c0e062012-05-28 13:45:35 -0700696static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
697 etm_store_addr_single);
698
699static ssize_t etm_show_addr_range(struct device *dev,
700 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800701{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700702 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700703 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800704 uint8_t idx;
705
Pratik Patel16aefdb2012-05-30 10:41:23 -0700706 mutex_lock(&drvdata->mutex);
707 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700708 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700709 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700710 return -EPERM;
711 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700712 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
713 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
714 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
715 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
716 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800717 return -EPERM;
718 }
719
Pratik Patel16aefdb2012-05-30 10:41:23 -0700720 val1 = drvdata->addr_val[idx];
721 val2 = drvdata->addr_val[idx + 1];
722 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700723 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800724}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800725
Pratik Patela9c0e062012-05-28 13:45:35 -0700726static ssize_t etm_store_addr_range(struct device *dev,
727 struct device_attribute *attr,
728 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800729{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700730 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800731 unsigned long val1, val2;
732 uint8_t idx;
733
734 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
735 return -EINVAL;
736 /* lower address comparator cannot have a higher address value */
737 if (val1 > val2)
738 return -EINVAL;
739
Pratik Patel16aefdb2012-05-30 10:41:23 -0700740 mutex_lock(&drvdata->mutex);
741 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800742 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700743 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800744 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 drvdata->addr_val[idx] = val1;
755 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
756 drvdata->addr_val[idx + 1] = val2;
757 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
758 drvdata->enable_ctrl1 |= (1 << (idx/2));
759 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700760 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800761}
Pratik Patela9c0e062012-05-28 13:45:35 -0700762static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
763 etm_store_addr_range);
764
765static ssize_t etm_show_addr_start(struct device *dev,
766 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800767{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700768 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700769 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800770 uint8_t idx;
771
Pratik Patel16aefdb2012-05-30 10:41:23 -0700772 mutex_lock(&drvdata->mutex);
773 idx = drvdata->addr_idx;
774 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
775 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
776 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800777 return -EPERM;
778 }
779
Pratik Patel16aefdb2012-05-30 10:41:23 -0700780 val = drvdata->addr_val[idx];
781 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700782 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800783}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800784
Pratik Patela9c0e062012-05-28 13:45:35 -0700785static ssize_t etm_store_addr_start(struct device *dev,
786 struct device_attribute *attr,
787 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800788{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700789 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800790 unsigned long val;
791 uint8_t idx;
792
793 if (sscanf(buf, "%lx", &val) != 1)
794 return -EINVAL;
795
Pratik Patel16aefdb2012-05-30 10:41:23 -0700796 mutex_lock(&drvdata->mutex);
797 idx = drvdata->addr_idx;
798 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
799 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
800 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800801 return -EPERM;
802 }
803
Pratik Patel16aefdb2012-05-30 10:41:23 -0700804 drvdata->addr_val[idx] = val;
805 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
806 drvdata->startstop_ctrl |= (1 << idx);
807 drvdata->enable_ctrl1 |= BIT(25);
808 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700809 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800810}
Pratik Patela9c0e062012-05-28 13:45:35 -0700811static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
812 etm_store_addr_start);
813
814static ssize_t etm_show_addr_stop(struct device *dev,
815 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800816{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700817 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800818 unsigned long val;
819 uint8_t idx;
820
Pratik Patel16aefdb2012-05-30 10:41:23 -0700821 mutex_lock(&drvdata->mutex);
822 idx = drvdata->addr_idx;
823 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
824 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
825 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800826 return -EPERM;
827 }
828
Pratik Patel16aefdb2012-05-30 10:41:23 -0700829 val = drvdata->addr_val[idx];
830 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800831 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
832}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800833
Pratik Patela9c0e062012-05-28 13:45:35 -0700834static ssize_t etm_store_addr_stop(struct device *dev,
835 struct device_attribute *attr,
836 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800837{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700838 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800839 unsigned long val;
840 uint8_t idx;
841
842 if (sscanf(buf, "%lx", &val) != 1)
843 return -EINVAL;
844
Pratik Patel16aefdb2012-05-30 10:41:23 -0700845 mutex_lock(&drvdata->mutex);
846 idx = drvdata->addr_idx;
847 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
848 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
849 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800850 return -EPERM;
851 }
852
Pratik Patel16aefdb2012-05-30 10:41:23 -0700853 drvdata->addr_val[idx] = val;
854 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
855 drvdata->startstop_ctrl |= (1 << (idx + 16));
856 drvdata->enable_ctrl1 |= BIT(25);
857 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700858 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800859}
Pratik Patela9c0e062012-05-28 13:45:35 -0700860static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
861 etm_store_addr_stop);
862
863static ssize_t etm_show_addr_acctype(struct device *dev,
864 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800865{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700866 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800867 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800868
Pratik Patel16aefdb2012-05-30 10:41:23 -0700869 mutex_lock(&drvdata->mutex);
870 val = drvdata->addr_acctype[drvdata->addr_idx];
871 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800872 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
873}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800874
Pratik Patela9c0e062012-05-28 13:45:35 -0700875static ssize_t etm_store_addr_acctype(struct device *dev,
876 struct device_attribute *attr,
877 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800878{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700879 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800880 unsigned long val;
881
882 if (sscanf(buf, "%lx", &val) != 1)
883 return -EINVAL;
884
Pratik Patel16aefdb2012-05-30 10:41:23 -0700885 mutex_lock(&drvdata->mutex);
886 drvdata->addr_acctype[drvdata->addr_idx] = val;
887 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700888 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800889}
Pratik Patela9c0e062012-05-28 13:45:35 -0700890static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
891 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800892
Pratik Patela9c0e062012-05-28 13:45:35 -0700893static ssize_t etm_show_cntr_idx(struct device *dev,
894 struct device_attribute *attr, char *buf)
895{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700896 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700897 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700898
Pratik Patel6630ebe2012-03-06 16:44:22 -0800899 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
900}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800901
Pratik Patela9c0e062012-05-28 13:45:35 -0700902static ssize_t etm_store_cntr_idx(struct device *dev,
903 struct device_attribute *attr,
904 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800905{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700906 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800907 unsigned long val;
908
909 if (sscanf(buf, "%lx", &val) != 1)
910 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700911 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800912 return -EINVAL;
913
914 /* Use mutex to ensure index doesn't change while it gets dereferenced
915 * multiple times within a mutex block elsewhere.
916 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700917 mutex_lock(&drvdata->mutex);
918 drvdata->cntr_idx = val;
919 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700920 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800921}
Pratik Patela9c0e062012-05-28 13:45:35 -0700922static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
923 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800924
Pratik Patela9c0e062012-05-28 13:45:35 -0700925static ssize_t etm_show_cntr_rld_val(struct device *dev,
926 struct device_attribute *attr, char *buf)
927{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700928 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700929 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700930
Pratik Patel16aefdb2012-05-30 10:41:23 -0700931 mutex_lock(&drvdata->mutex);
932 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
933 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700934 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
935}
936
937static ssize_t etm_store_cntr_rld_val(struct device *dev,
938 struct device_attribute *attr,
939 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800940{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700941 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800942 unsigned long val;
943
944 if (sscanf(buf, "%lx", &val) != 1)
945 return -EINVAL;
946
Pratik Patel16aefdb2012-05-30 10:41:23 -0700947 mutex_lock(&drvdata->mutex);
948 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
949 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700950 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800951}
Pratik Patela9c0e062012-05-28 13:45:35 -0700952static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
953 etm_store_cntr_rld_val);
954
955static ssize_t etm_show_cntr_event(struct device *dev,
956 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800957{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700958 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800959 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700960
Pratik Patel16aefdb2012-05-30 10:41:23 -0700961 mutex_lock(&drvdata->mutex);
962 val = drvdata->cntr_event[drvdata->cntr_idx];
963 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800964 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
965}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800966
Pratik Patela9c0e062012-05-28 13:45:35 -0700967static ssize_t etm_store_cntr_event(struct device *dev,
968 struct device_attribute *attr,
969 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800970{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700971 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800972 unsigned long val;
973
974 if (sscanf(buf, "%lx", &val) != 1)
975 return -EINVAL;
976
Pratik Patel16aefdb2012-05-30 10:41:23 -0700977 mutex_lock(&drvdata->mutex);
978 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
979 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700980 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800981}
Pratik Patela9c0e062012-05-28 13:45:35 -0700982static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
983 etm_store_cntr_event);
984
985static ssize_t etm_show_cntr_rld_event(struct device *dev,
986 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800987{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700988 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800989 unsigned long val;
990
Pratik Patel16aefdb2012-05-30 10:41:23 -0700991 mutex_lock(&drvdata->mutex);
992 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
993 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800994 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
995}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800996
Pratik Patela9c0e062012-05-28 13:45:35 -0700997static ssize_t etm_store_cntr_rld_event(struct device *dev,
998 struct device_attribute *attr,
999 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001000{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001001 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001002 unsigned long val;
1003
1004 if (sscanf(buf, "%lx", &val) != 1)
1005 return -EINVAL;
1006
Pratik Patel16aefdb2012-05-30 10:41:23 -07001007 mutex_lock(&drvdata->mutex);
1008 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1009 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001010 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001011}
Pratik Patela9c0e062012-05-28 13:45:35 -07001012static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1013 etm_store_cntr_rld_event);
1014
1015static ssize_t etm_show_cntr_val(struct device *dev,
1016 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001017{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001018 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001019 unsigned long val;
1020
Pratik Patel16aefdb2012-05-30 10:41:23 -07001021 mutex_lock(&drvdata->mutex);
1022 val = drvdata->cntr_val[drvdata->cntr_idx];
1023 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001024 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1025}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001026
Pratik Patela9c0e062012-05-28 13:45:35 -07001027static ssize_t etm_store_cntr_val(struct device *dev,
1028 struct device_attribute *attr,
1029 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001030{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001031 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001032 unsigned long val;
1033
1034 if (sscanf(buf, "%lx", &val) != 1)
1035 return -EINVAL;
1036
Pratik Patel16aefdb2012-05-30 10:41:23 -07001037 mutex_lock(&drvdata->mutex);
1038 drvdata->cntr_val[drvdata->cntr_idx] = val;
1039 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001040 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001041}
Pratik Patela9c0e062012-05-28 13:45:35 -07001042static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1043 etm_store_cntr_val);
1044
1045static ssize_t etm_show_seq_12_event(struct device *dev,
1046 struct device_attribute *attr, char *buf)
1047{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001048 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001049 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001050
Pratik Patela9c0e062012-05-28 13:45:35 -07001051 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1052}
1053
1054static ssize_t etm_store_seq_12_event(struct device *dev,
1055 struct device_attribute *attr,
1056 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001057{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001058 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001059 unsigned long val;
1060
Pratik Patela9c0e062012-05-28 13:45:35 -07001061 if (sscanf(buf, "%lx", &val) != 1)
1062 return -EINVAL;
1063
Pratik Patel16aefdb2012-05-30 10:41:23 -07001064 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001065 return size;
1066}
1067static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1068 etm_store_seq_12_event);
1069
1070static ssize_t etm_show_seq_21_event(struct device *dev,
1071 struct device_attribute *attr, char *buf)
1072{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001073 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001074 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001075
Pratik Patel6630ebe2012-03-06 16:44:22 -08001076 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1077}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001078
Pratik Patela9c0e062012-05-28 13:45:35 -07001079static ssize_t etm_store_seq_21_event(struct device *dev,
1080 struct device_attribute *attr,
1081 const char *buf, size_t size)
1082{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001083 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001084 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001085
Pratik Patela9c0e062012-05-28 13:45:35 -07001086 if (sscanf(buf, "%lx", &val) != 1)
1087 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001088
Pratik Patel16aefdb2012-05-30 10:41:23 -07001089 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001090 return size;
1091}
1092static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1093 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001094
Pratik Patela9c0e062012-05-28 13:45:35 -07001095static ssize_t etm_show_seq_23_event(struct device *dev,
1096 struct device_attribute *attr, char *buf)
1097{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001098 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001099 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001100
Pratik Patela9c0e062012-05-28 13:45:35 -07001101 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1102}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001103
Pratik Patela9c0e062012-05-28 13:45:35 -07001104static ssize_t etm_store_seq_23_event(struct device *dev,
1105 struct device_attribute *attr,
1106 const char *buf, size_t size)
1107{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001108 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001109 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001110
Pratik Patela9c0e062012-05-28 13:45:35 -07001111 if (sscanf(buf, "%lx", &val) != 1)
1112 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001113
Pratik Patel16aefdb2012-05-30 10:41:23 -07001114 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001115 return size;
1116}
1117static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1118 etm_store_seq_23_event);
1119
1120static ssize_t etm_show_seq_31_event(struct device *dev,
1121 struct device_attribute *attr, char *buf)
1122{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001123 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001124 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001125
Pratik Patela9c0e062012-05-28 13:45:35 -07001126 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1127}
1128
1129static ssize_t etm_store_seq_31_event(struct device *dev,
1130 struct device_attribute *attr,
1131 const char *buf, size_t size)
1132{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001133 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001134 unsigned long val;
1135
1136 if (sscanf(buf, "%lx", &val) != 1)
1137 return -EINVAL;
1138
Pratik Patel16aefdb2012-05-30 10:41:23 -07001139 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001140 return size;
1141}
1142static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1143 etm_store_seq_31_event);
1144
1145static ssize_t etm_show_seq_32_event(struct device *dev,
1146 struct device_attribute *attr, char *buf)
1147{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001148 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001149 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001150
Pratik Patela9c0e062012-05-28 13:45:35 -07001151 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1152}
1153
1154static ssize_t etm_store_seq_32_event(struct device *dev,
1155 struct device_attribute *attr,
1156 const char *buf, size_t size)
1157{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001158 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001159 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 Patel3b0ca882012-06-01 16:54:14 -07001173 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001174 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001175
Pratik Patela9c0e062012-05-28 13:45:35 -07001176 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1177}
1178
1179static ssize_t etm_store_seq_13_event(struct device *dev,
1180 struct device_attribute *attr,
1181 const char *buf, size_t size)
1182{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001183 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001184 unsigned long val;
1185
1186 if (sscanf(buf, "%lx", &val) != 1)
1187 return -EINVAL;
1188
Pratik Patel16aefdb2012-05-30 10:41:23 -07001189 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001190 return size;
1191}
1192static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1193 etm_store_seq_13_event);
1194
1195static ssize_t etm_show_seq_curr_state(struct device *dev,
1196 struct device_attribute *attr, char *buf)
1197{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001198 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001199 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001200
Pratik Patela9c0e062012-05-28 13:45:35 -07001201 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1202}
1203
1204static ssize_t etm_store_seq_curr_state(struct device *dev,
1205 struct device_attribute *attr,
1206 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001207{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001208 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001209 unsigned long val;
1210
1211 if (sscanf(buf, "%lx", &val) != 1)
1212 return -EINVAL;
1213 if (val > ETM_SEQ_STATE_MAX_VAL)
1214 return -EINVAL;
1215
Pratik Patel16aefdb2012-05-30 10:41:23 -07001216 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001217 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001218}
Pratik Patela9c0e062012-05-28 13:45:35 -07001219static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1220 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001221
Pratik Patela9c0e062012-05-28 13:45:35 -07001222static ssize_t etm_show_ctxid_idx(struct device *dev,
1223 struct device_attribute *attr, char *buf)
1224{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001225 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001226 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001227
Pratik Patela9c0e062012-05-28 13:45:35 -07001228 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1229}
1230
1231static ssize_t etm_store_ctxid_idx(struct device *dev,
1232 struct device_attribute *attr,
1233 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001234{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001235 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001236 unsigned long val;
1237
1238 if (sscanf(buf, "%lx", &val) != 1)
1239 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001240 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001241 return -EINVAL;
1242
1243 /* Use mutex to ensure index doesn't change while it gets dereferenced
1244 * multiple times within a mutex block elsewhere.
1245 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001246 mutex_lock(&drvdata->mutex);
1247 drvdata->ctxid_idx = val;
1248 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001249 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001250}
Pratik Patela9c0e062012-05-28 13:45:35 -07001251static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1252 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001253
Pratik Patela9c0e062012-05-28 13:45:35 -07001254static ssize_t etm_show_ctxid_val(struct device *dev,
1255 struct device_attribute *attr, char *buf)
1256{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001257 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001258 unsigned long val;
1259
Pratik Patel16aefdb2012-05-30 10:41:23 -07001260 mutex_lock(&drvdata->mutex);
1261 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1262 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001263 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1264}
1265
1266static ssize_t etm_store_ctxid_val(struct device *dev,
1267 struct device_attribute *attr,
1268 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001269{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001270 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001271 unsigned long val;
1272
1273 if (sscanf(buf, "%lx", &val) != 1)
1274 return -EINVAL;
1275
Pratik Patel16aefdb2012-05-30 10:41:23 -07001276 mutex_lock(&drvdata->mutex);
1277 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1278 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001279 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001280}
Pratik Patela9c0e062012-05-28 13:45:35 -07001281static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1282 etm_store_ctxid_val);
1283
1284static ssize_t etm_show_ctxid_mask(struct device *dev,
1285 struct device_attribute *attr, char *buf)
1286{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001287 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001288 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001289
Pratik Patela9c0e062012-05-28 13:45:35 -07001290 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1291}
1292
1293static ssize_t etm_store_ctxid_mask(struct device *dev,
1294 struct device_attribute *attr,
1295 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001296{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001297 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001298 unsigned long val;
1299
Pratik Patela9c0e062012-05-28 13:45:35 -07001300 if (sscanf(buf, "%lx", &val) != 1)
1301 return -EINVAL;
1302
Pratik Patel16aefdb2012-05-30 10:41:23 -07001303 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001304 return size;
1305}
1306static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1307 etm_store_ctxid_mask);
1308
1309static ssize_t etm_show_sync_freq(struct device *dev,
1310 struct device_attribute *attr, char *buf)
1311{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001312 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001313 unsigned long val = drvdata->sync_freq;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001314 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1315}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001316
Pratik Patela9c0e062012-05-28 13:45:35 -07001317static ssize_t etm_store_sync_freq(struct device *dev,
1318 struct device_attribute *attr,
1319 const char *buf, size_t size)
1320{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001321 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001322 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001323
Pratik Patela9c0e062012-05-28 13:45:35 -07001324 if (sscanf(buf, "%lx", &val) != 1)
1325 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001326
Pratik Patel16aefdb2012-05-30 10:41:23 -07001327 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001328 return size;
1329}
1330static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1331 etm_store_sync_freq);
1332
1333static ssize_t etm_show_timestamp_event(struct device *dev,
1334 struct device_attribute *attr,
1335 char *buf)
1336{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001337 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001338 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001339
Pratik Patela9c0e062012-05-28 13:45:35 -07001340 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1341}
1342
1343static ssize_t etm_store_timestamp_event(struct device *dev,
1344 struct device_attribute *attr,
1345 const char *buf, size_t size)
1346{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001347 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001348 unsigned long val;
1349
1350 if (sscanf(buf, "%lx", &val) != 1)
1351 return -EINVAL;
1352
Pratik Patel16aefdb2012-05-30 10:41:23 -07001353 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001354 return size;
1355}
1356static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1357 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001358
1359static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001360 &dev_attr_nr_addr_cmp.attr,
1361 &dev_attr_nr_cntr.attr,
1362 &dev_attr_nr_ctxid_cmp.attr,
1363 &dev_attr_reset.attr,
1364 &dev_attr_mode.attr,
1365 &dev_attr_trigger_event.attr,
1366 &dev_attr_enable_event.attr,
1367 &dev_attr_fifofull_level.attr,
1368 &dev_attr_addr_idx.attr,
1369 &dev_attr_addr_single.attr,
1370 &dev_attr_addr_range.attr,
1371 &dev_attr_addr_start.attr,
1372 &dev_attr_addr_stop.attr,
1373 &dev_attr_addr_acctype.attr,
1374 &dev_attr_cntr_idx.attr,
1375 &dev_attr_cntr_rld_val.attr,
1376 &dev_attr_cntr_event.attr,
1377 &dev_attr_cntr_rld_event.attr,
1378 &dev_attr_cntr_val.attr,
1379 &dev_attr_seq_12_event.attr,
1380 &dev_attr_seq_21_event.attr,
1381 &dev_attr_seq_23_event.attr,
1382 &dev_attr_seq_31_event.attr,
1383 &dev_attr_seq_32_event.attr,
1384 &dev_attr_seq_13_event.attr,
1385 &dev_attr_seq_curr_state.attr,
1386 &dev_attr_ctxid_idx.attr,
1387 &dev_attr_ctxid_val.attr,
1388 &dev_attr_ctxid_mask.attr,
1389 &dev_attr_sync_freq.attr,
1390 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001391 NULL,
1392};
1393
1394static struct attribute_group etm_attr_grp = {
1395 .attrs = etm_attrs,
1396};
1397
Pratik Patel3b0ca882012-06-01 16:54:14 -07001398static const struct attribute_group *etm_attr_grps[] = {
1399 &etm_attr_grp,
1400 NULL,
1401};
1402
1403/* Memory mapped writes to clear os lock not supported */
1404static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001405{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001406 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001407
Pratik Patel3b0ca882012-06-01 16:54:14 -07001408 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1409 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001410}
1411
Stephen Boyda9510502012-04-24 16:23:34 -07001412static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001413{
Pratik Patel61de7302012-03-07 12:06:10 -08001414 switch (arch) {
1415 case PFT_ARCH_V1_1:
1416 break;
1417 default:
1418 return false;
1419 }
1420 return true;
1421}
1422
Pratik Patel3b0ca882012-06-01 16:54:14 -07001423static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
Pratik Patel61de7302012-03-07 12:06:10 -08001424{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001425 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -08001426 uint32_t etmidr;
1427 uint32_t etmccr;
Pratik Patel7831c082011-06-08 21:44:37 -07001428
Pratik Patel17f3b822011-11-21 12:41:47 -08001429 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel492b3012012-03-06 14:22:30 -08001430 etm_os_unlock(NULL);
1431 smp_call_function(etm_os_unlock, NULL, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001432 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001433 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001434 etm_clr_pwrdwn(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001435 /* Set prog bit. It will be set from reset but this is included to
1436 * ensure it is set
1437 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001438 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001439
1440 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001441 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001442 drvdata->arch = BMVAL(etmidr, 4, 11);
1443 if (etm_arch_supported(drvdata->arch) == false) {
Pratik Patel61de7302012-03-07 12:06:10 -08001444 ret = -EINVAL;
1445 goto err;
1446 }
Pratik Patel7831c082011-06-08 21:44:37 -07001447
Pratik Patel3b0ca882012-06-01 16:54:14 -07001448 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001449 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1450 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1451 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1452 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1453 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001454
Pratik Patel17f3b822011-11-21 12:41:47 -08001455 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001456 etm_set_pwrdwn(drvdata);
1457 ETM_LOCK(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001458
1459 return 0;
1460err:
1461 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001462}
1463
Pratik Patelc14b4df2012-09-05 18:07:59 -07001464static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1465{
1466 drvdata->arch = etm0drvdata->arch;
1467 drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
1468 drvdata->nr_cntr = etm0drvdata->nr_cntr;
1469 drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
1470 drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
1471 drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
1472}
1473
Pratik Patel3b0ca882012-06-01 16:54:14 -07001474static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001475{
1476 int i;
1477
1478 drvdata->trigger_event = 0x406F;
1479 drvdata->enable_event = 0x6F;
1480 drvdata->enable_ctrl1 = 0x1;
1481 drvdata->fifofull_level = 0x28;
1482 if (drvdata->nr_addr_cmp >= 2) {
1483 drvdata->addr_val[0] = (uint32_t) _stext;
1484 drvdata->addr_val[1] = (uint32_t) _etext;
1485 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1486 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1487 }
1488 for (i = 0; i < drvdata->nr_cntr; i++) {
1489 drvdata->cntr_event[i] = 0x406F;
1490 drvdata->cntr_rld_event[i] = 0x406F;
1491 }
1492 drvdata->seq_12_event = 0x406F;
1493 drvdata->seq_21_event = 0x406F;
1494 drvdata->seq_23_event = 0x406F;
1495 drvdata->seq_31_event = 0x406F;
1496 drvdata->seq_32_event = 0x406F;
1497 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001498 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1499 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1500 drvdata->sync_freq = 0x100;
1501 else
1502 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001503 drvdata->timestamp_event = 0x406F;
1504
1505 /* Overrides for Krait pass1 */
1506 if (cpu_is_krait_v1()) {
1507 /* Krait pass1 doesn't support include filtering and non-cycle
1508 * accurate tracing
1509 */
1510 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1511 drvdata->ctrl = 0x1000;
1512 drvdata->enable_ctrl1 = 0x1000000;
1513 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1514 drvdata->addr_val[i] = 0x0;
1515 drvdata->addr_acctype[i] = 0x0;
1516 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1517 }
1518 }
1519}
1520
Pratik Patel492b3012012-03-06 14:22:30 -08001521static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001522{
Pratik Patele5771792011-09-17 18:33:54 -07001523 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001524 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001525 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001526 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001527 struct resource *res;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001528 static int etm_count;
1529 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001530
Pratik Patel670627c2012-08-19 13:50:51 -07001531 /* Fail probe for Krait pass3 until supported */
1532 if (cpu_is_krait_v3()) {
1533 dev_info(dev, "ETM: failing probe for Krait pass3\n");
1534 return -EINVAL;
1535 }
1536
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001537 if (pdev->dev.of_node) {
1538 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1539 if (IS_ERR(pdata))
1540 return PTR_ERR(pdata);
1541 pdev->dev.platform_data = pdata;
1542 }
1543
Pratik Patel4a1b2522012-06-17 15:31:15 -07001544 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1545 if (!drvdata)
1546 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001547 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001548 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001549
Pratik Patel4a1b2522012-06-17 15:31:15 -07001550 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1551 if (!res)
1552 return -ENODEV;
Pratik Patel2c09b762012-07-21 15:54:54 -07001553
Pratik Patel4a1b2522012-06-17 15:31:15 -07001554 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1555 if (!drvdata->base)
1556 return -ENOMEM;
1557
Pratik Patel16aefdb2012-05-30 10:41:23 -07001558 mutex_init(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001559 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001560 pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
1561 PM_QOS_DEFAULT_VALUE);
Pratik Patele10a77c2012-03-20 10:35:16 -07001562
Pratik Patel4a1b2522012-06-17 15:31:15 -07001563 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001564 if (IS_ERR(drvdata->clk)) {
1565 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001566 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001567 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001568
Pratik Patel6fb38342012-06-03 14:51:38 -07001569 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001570 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001571 goto err0;
1572
1573 drvdata->cpu = etm_count++;
1574
Pratik Patel16aefdb2012-05-30 10:41:23 -07001575 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001576 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001577 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001578
Pratik Patelc14b4df2012-09-05 18:07:59 -07001579 /* Use CPU0 to populate read-only configuration data for ETM0. For other
1580 * ETMs copy it over from ETM0.
1581 */
1582 if (drvdata->cpu == 0) {
1583 ret = etm_init_arch_data(drvdata);
1584 if (ret)
1585 goto err1;
1586 etm0drvdata = drvdata;
1587 } else {
1588 if (etm0drvdata)
1589 etm_copy_arch_data(drvdata);
1590 else
1591 goto err1;
1592 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001593 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001594
Pratik Patel16aefdb2012-05-30 10:41:23 -07001595 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001596
Pratik Patel4a1b2522012-06-17 15:31:15 -07001597 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001598 if (!desc) {
1599 ret = -ENOMEM;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001600 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001601 }
1602 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1603 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1604 desc->ops = &etm_cs_ops;
1605 desc->pdata = pdev->dev.platform_data;
1606 desc->dev = &pdev->dev;
1607 desc->groups = etm_attr_grps;
1608 desc->owner = THIS_MODULE;
1609 drvdata->csdev = coresight_register(desc);
1610 if (IS_ERR(drvdata->csdev)) {
1611 ret = PTR_ERR(drvdata->csdev);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001612 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001613 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001614
Pratik Patel4a1b2522012-06-17 15:31:15 -07001615 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001616
Pratik Patel3b0ca882012-06-01 16:54:14 -07001617 if (boot_enable)
1618 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001619
1620 return 0;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001621err1:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001622 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001623err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001624 pm_qos_remove_request(&drvdata->qos_req);
1625 wake_lock_destroy(&drvdata->wake_lock);
1626 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001627 return ret;
1628}
1629
Pratik Patelf6fe9182012-03-20 14:04:18 -07001630static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001631{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001632 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1633
1634 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001635 pm_qos_remove_request(&drvdata->qos_req);
1636 wake_lock_destroy(&drvdata->wake_lock);
1637 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001638 return 0;
1639}
1640
Pratik Patel9eae4822012-05-14 17:34:53 -07001641static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001642 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001643 {}
1644};
1645
Pratik Patel492b3012012-03-06 14:22:30 -08001646static struct platform_driver etm_driver = {
1647 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001648 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001649 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001650 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001651 .owner = THIS_MODULE,
1652 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001653 },
1654};
1655
Pratik Patel492b3012012-03-06 14:22:30 -08001656int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001657{
Pratik Patel492b3012012-03-06 14:22:30 -08001658 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001659}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001660module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001661
Pratik Patelf6fe9182012-03-20 14:04:18 -07001662void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001663{
Pratik Patel492b3012012-03-06 14:22:30 -08001664 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001665}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001666module_exit(etm_exit);
1667
1668MODULE_LICENSE("GPL v2");
1669MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");