blob: 182e50c88f3faf33edd5d61175b114132ebd8f27 [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>
Pratik Patel6630ebe2012-03-06 16:44:22 -080026#include <linux/sysfs.h>
27#include <linux/stat.h>
Pratik Patel3b0ca882012-06-01 16:54:14 -070028#include <linux/mutex.h>
Pratik Patelf17b1472012-05-25 22:23:52 -070029#include <linux/clk.h>
Pratik Patel5f6d1af2012-06-13 15:48:13 -070030#include <linux/of_coresight.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#define etm_writel(drvdata, val, off) \
38 __raw_writel((val), drvdata->base + off)
39#define etm_readl(drvdata, off) \
40 __raw_readl(drvdata->base + off)
41
42#define ETM_LOCK(drvdata) \
43do { \
44 mb(); \
45 etm_writel(drvdata, 0x0, CORESIGHT_LAR); \
46} while (0)
47#define ETM_UNLOCK(drvdata) \
48do { \
49 etm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
50 mb(); \
51} while (0)
52
Pratik Patel7831c082011-06-08 21:44:37 -070053/*
54 * Device registers:
55 * 0x000 - 0x2FC: Trace registers
56 * 0x300 - 0x314: Management registers
57 * 0x318 - 0xEFC: Trace registers
58 *
59 * Coresight registers
60 * 0xF00 - 0xF9C: Management registers
61 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
62 * Trace registers in PFTv1.1
63 * 0xFA8 - 0xFFC: Management registers
64 */
65
66/* Trace registers (0x000-0x2FC) */
67#define ETMCR (0x000)
68#define ETMCCR (0x004)
69#define ETMTRIGGER (0x008)
70#define ETMSR (0x010)
71#define ETMSCR (0x014)
72#define ETMTSSCR (0x018)
73#define ETMTEEVR (0x020)
74#define ETMTECR1 (0x024)
75#define ETMFFLR (0x02C)
76#define ETMACVRn(n) (0x040 + (n * 4))
77#define ETMACTRn(n) (0x080 + (n * 4))
78#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
79#define ETMCNTENRn(n) (0x150 + (n * 4))
80#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
81#define ETMCNTVRn(n) (0x170 + (n * 4))
82#define ETMSQ12EVR (0x180)
83#define ETMSQ21EVR (0x184)
84#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -080085#define ETMSQ31EVR (0x18C)
86#define ETMSQ32EVR (0x190)
87#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -070088#define ETMSQR (0x19C)
89#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
90#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
91#define ETMCIDCMR (0x1BC)
92#define ETMIMPSPEC0 (0x1C0)
93#define ETMIMPSPEC1 (0x1C4)
94#define ETMIMPSPEC2 (0x1C8)
95#define ETMIMPSPEC3 (0x1CC)
96#define ETMIMPSPEC4 (0x1D0)
97#define ETMIMPSPEC5 (0x1D4)
98#define ETMIMPSPEC6 (0x1D8)
99#define ETMIMPSPEC7 (0x1DC)
100#define ETMSYNCFR (0x1E0)
101#define ETMIDR (0x1E4)
102#define ETMCCER (0x1E8)
103#define ETMEXTINSELR (0x1EC)
104#define ETMTESSEICR (0x1F0)
105#define ETMEIBCR (0x1F4)
106#define ETMTSEVR (0x1F8)
107#define ETMAUXCR (0x1FC)
108#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800109#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700110/* Management registers (0x300-0x314) */
111#define ETMOSLAR (0x300)
112#define ETMOSLSR (0x304)
113#define ETMOSSRR (0x308)
114#define ETMPDCR (0x310)
115#define ETMPDSR (0x314)
116
Pratik Patel61de7302012-03-07 12:06:10 -0800117#define ETM_MAX_ADDR_CMP (16)
118#define ETM_MAX_CNTR (4)
119#define ETM_MAX_CTXID_CMP (3)
120
Pratik Patel6630ebe2012-03-06 16:44:22 -0800121#define ETM_MODE_EXCLUDE BIT(0)
122#define ETM_MODE_CYCACC BIT(1)
123#define ETM_MODE_STALL BIT(2)
124#define ETM_MODE_TIMESTAMP BIT(3)
125#define ETM_MODE_CTXID BIT(4)
126#define ETM_MODE_ALL (0x1F)
127
128#define ETM_EVENT_MASK (0x1FFFF)
129#define ETM_SYNC_MASK (0xFFF)
130#define ETM_ALL_MASK (0xFFFFFFFF)
131
132#define ETM_SEQ_STATE_MAX_VAL (0x2)
133
Pratik Patel3b0ca882012-06-01 16:54:14 -0700134enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800135 ETM_ADDR_TYPE_NONE,
136 ETM_ADDR_TYPE_SINGLE,
137 ETM_ADDR_TYPE_RANGE,
138 ETM_ADDR_TYPE_START,
139 ETM_ADDR_TYPE_STOP,
140};
141
Pratik Patel29cba152012-01-03 11:40:26 -0800142#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700143static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800144#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700145static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800146#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700147module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700148 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700149);
150
Pratik Patel16aefdb2012-05-30 10:41:23 -0700151struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700152 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700153 struct device *dev;
154 struct coresight_device *csdev;
155 struct clk *clk;
156 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700157 struct wake_lock wake_lock;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700158 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800159 uint8_t arch;
160 uint8_t nr_addr_cmp;
161 uint8_t nr_cntr;
162 uint8_t nr_ext_inp;
163 uint8_t nr_ext_out;
164 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800165 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800166 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800167 uint32_t ctrl;
168 uint32_t trigger_event;
169 uint32_t startstop_ctrl;
170 uint32_t enable_event;
171 uint32_t enable_ctrl1;
172 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800173 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800174 uint32_t addr_val[ETM_MAX_ADDR_CMP];
175 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800176 uint32_t addr_type[ETM_MAX_ADDR_CMP];
177 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800178 uint32_t cntr_rld_val[ETM_MAX_CNTR];
179 uint32_t cntr_event[ETM_MAX_CNTR];
180 uint32_t cntr_rld_event[ETM_MAX_CNTR];
181 uint32_t cntr_val[ETM_MAX_CNTR];
182 uint32_t seq_12_event;
183 uint32_t seq_21_event;
184 uint32_t seq_23_event;
185 uint32_t seq_31_event;
186 uint32_t seq_32_event;
187 uint32_t seq_13_event;
188 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800189 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800190 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
191 uint32_t ctxid_mask;
192 uint32_t sync_freq;
193 uint32_t timestamp_event;
Pratik Patel7831c082011-06-08 21:44:37 -0700194};
195
Pratik Patelc14b4df2012-09-05 18:07:59 -0700196static struct etm_drvdata *etm0drvdata;
197
Pratik Patel17f3b822011-11-21 12:41:47 -0800198/* ETM clock is derived from the processor clock and gets enabled on a
199 * logical OR of below items on Krait (pass2 onwards):
200 * 1.CPMR[ETMCLKEN] is 1
201 * 2.ETMCR[PD] is 0
202 * 3.ETMPDCR[PU] is 1
203 * 4.Reset is asserted (core or debug)
204 * 5.APB memory mapped requests (eg. EDAP access)
205 *
206 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
207 * enables
208 *
209 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
210 * clock vote in the driver and the save-restore code uses 1. above
211 * for its vote
212 */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700213static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700214{
215 uint32_t etmcr;
216
Pratik Patel3b0ca882012-06-01 16:54:14 -0700217 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700218 etmcr |= BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700219 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700220}
221
Pratik Patel3b0ca882012-06-01 16:54:14 -0700222static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700223{
224 uint32_t etmcr;
225
Pratik Patel3b0ca882012-06-01 16:54:14 -0700226 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700227 etmcr &= ~BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700228 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700229}
230
Pratik Patel3b0ca882012-06-01 16:54:14 -0700231static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700232{
233 uint32_t etmcr;
234 int count;
235
Pratik Patel3b0ca882012-06-01 16:54:14 -0700236 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700237 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700238 etm_writel(drvdata, etmcr, ETMCR);
239 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700240 && count > 0; count--)
241 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800242 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700243 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700244}
245
Pratik Patel3b0ca882012-06-01 16:54:14 -0700246static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700247{
248 uint32_t etmcr;
249 int count;
250
Pratik Patel3b0ca882012-06-01 16:54:14 -0700251 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700252 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700253 etm_writel(drvdata, etmcr, ETMCR);
254 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700255 && count > 0; count--)
256 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800257 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700258 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700259}
260
Pratik Patel66e1a412012-09-06 11:07:06 -0700261static void __etm_enable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700262{
Pratik Patel17f3b822011-11-21 12:41:47 -0800263 int i;
Pratik Patel66e1a412012-09-06 11:07:06 -0700264 struct etm_drvdata *drvdata = info;
Pratik Patel7831c082011-06-08 21:44:37 -0700265
Pratik Patel3b0ca882012-06-01 16:54:14 -0700266 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800267 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700268 etm_clr_pwrdwn(drvdata);
269 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700270
Pratik Patel3b0ca882012-06-01 16:54:14 -0700271 etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
272 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
273 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
274 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
275 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
276 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700277 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700278 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
279 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700280 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700281 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700282 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
283 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
284 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700285 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700286 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800287 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700288 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
289 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
290 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
291 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
292 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
293 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
294 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700295 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700296 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700297 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700298 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
299 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
300 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
301 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
302 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
303 etm_writel(drvdata, 0x00000000, ETMAUXCR);
304 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
305 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800306
Pratik Patel3b0ca882012-06-01 16:54:14 -0700307 etm_clr_prog(drvdata);
308 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700309
310 dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700311}
312
Pratik Patel3b0ca882012-06-01 16:54:14 -0700313static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700314{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700315 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
316 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800317
Pratik Patel16aefdb2012-05-30 10:41:23 -0700318 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700319
Pratik Patel16aefdb2012-05-30 10:41:23 -0700320 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700321 if (ret)
322 goto err_clk;
323
Pratik Patel3b0ca882012-06-01 16:54:14 -0700324 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700325 /* executing __etm_enable on the cpu whose ETM is being enabled
326 * ensures that register writes occur when cpu is powered.
327 */
328 smp_call_function_single(drvdata->cpu, __etm_enable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700329 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700330
Pratik Patel16aefdb2012-05-30 10:41:23 -0700331 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700332
Pratik Patel16aefdb2012-05-30 10:41:23 -0700333 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700334 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700335err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700336 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800337 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700338}
339
Pratik Patel66e1a412012-09-06 11:07:06 -0700340static void __etm_disable(void *info)
Pratik Patel7831c082011-06-08 21:44:37 -0700341{
Pratik Patel66e1a412012-09-06 11:07:06 -0700342 struct etm_drvdata *drvdata = info;
343
Pratik Patel3b0ca882012-06-01 16:54:14 -0700344 ETM_UNLOCK(drvdata);
345 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700346
Pratik Patel17f3b822011-11-21 12:41:47 -0800347 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700348 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700349
Pratik Patel17f3b822011-11-21 12:41:47 -0800350 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700351 etm_set_pwrdwn(drvdata);
352 ETM_LOCK(drvdata);
Pratik Patel66e1a412012-09-06 11:07:06 -0700353
354 dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
Pratik Patel7831c082011-06-08 21:44:37 -0700355}
356
Pratik Patel3b0ca882012-06-01 16:54:14 -0700357static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700358{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700359 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800360
Pratik Patel16aefdb2012-05-30 10:41:23 -0700361 wake_lock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700362
Pratik Patel3b0ca882012-06-01 16:54:14 -0700363 mutex_lock(&drvdata->mutex);
Pratik Patel66e1a412012-09-06 11:07:06 -0700364 /* executing __etm_disable on the cpu whose ETM is being disabled
365 * ensures that register writes occur when cpu is powered.
366 */
367 smp_call_function_single(drvdata->cpu, __etm_disable, drvdata, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700368 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700369
Pratik Patel16aefdb2012-05-30 10:41:23 -0700370 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700371
Pratik Patel16aefdb2012-05-30 10:41:23 -0700372 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700373
Pratik Patel16aefdb2012-05-30 10:41:23 -0700374 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700375}
376
Pratik Patel3b0ca882012-06-01 16:54:14 -0700377static const struct coresight_ops_source etm_source_ops = {
378 .enable = etm_enable,
379 .disable = etm_disable,
380};
Pratik Patel17f3b822011-11-21 12:41:47 -0800381
Pratik Patel3b0ca882012-06-01 16:54:14 -0700382static const struct coresight_ops etm_cs_ops = {
383 .source_ops = &etm_source_ops,
384};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800385
Pratik Patela9c0e062012-05-28 13:45:35 -0700386static ssize_t etm_show_nr_addr_cmp(struct device *dev,
387 struct device_attribute *attr, char *buf)
388{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700389 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700390 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700391
Pratik Patela9c0e062012-05-28 13:45:35 -0700392 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
393}
394static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
395
396static ssize_t etm_show_nr_cntr(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_cntr;
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_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
405
406static ssize_t etm_show_nr_ctxid_cmp(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_ctxid_cmp;
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_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
415
416static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
417 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->reset;
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}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800424
Pratik Pateld30deda2012-02-01 14:40:55 -0800425/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700426static ssize_t etm_store_reset(struct device *dev,
427 struct device_attribute *attr, const char *buf,
428 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800429{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700430 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800431 int i;
432 unsigned long val;
433
434 if (sscanf(buf, "%lx", &val) != 1)
435 return -EINVAL;
436
Pratik Patel16aefdb2012-05-30 10:41:23 -0700437 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800438 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700439 drvdata->mode = ETM_MODE_EXCLUDE;
440 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800441 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700442 drvdata->mode |= ETM_MODE_CYCACC;
443 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800444 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700445 drvdata->trigger_event = 0x406F;
446 drvdata->startstop_ctrl = 0x0;
447 drvdata->enable_event = 0x6F;
448 drvdata->enable_ctrl1 = 0x1000000;
449 drvdata->fifofull_level = 0x28;
450 drvdata->addr_idx = 0x0;
451 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
452 drvdata->addr_val[i] = 0x0;
453 drvdata->addr_acctype[i] = 0x0;
454 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800455 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700456 drvdata->cntr_idx = 0x0;
457 for (i = 0; i < drvdata->nr_cntr; i++) {
458 drvdata->cntr_rld_val[i] = 0x0;
459 drvdata->cntr_event[i] = 0x406F;
460 drvdata->cntr_rld_event[i] = 0x406F;
461 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800462 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700463 drvdata->seq_12_event = 0x406F;
464 drvdata->seq_21_event = 0x406F;
465 drvdata->seq_23_event = 0x406F;
466 drvdata->seq_31_event = 0x406F;
467 drvdata->seq_32_event = 0x406F;
468 drvdata->seq_13_event = 0x406F;
469 drvdata->seq_curr_state = 0x0;
470 drvdata->ctxid_idx = 0x0;
471 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
472 drvdata->ctxid_val[i] = 0x0;
473 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700474 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
475 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
476 drvdata->sync_freq = 0x100;
477 else
478 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700479 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800480 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700481 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700482 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800483}
Pratik Patela9c0e062012-05-28 13:45:35 -0700484static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800485
Pratik Patela9c0e062012-05-28 13:45:35 -0700486static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
487 char *buf)
488{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700489 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700490 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700491
Pratik Patela9c0e062012-05-28 13:45:35 -0700492 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
493}
494
495static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
496 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800497{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700498 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800499 unsigned long val;
500
501 if (sscanf(buf, "%lx", &val) != 1)
502 return -EINVAL;
503
Pratik Patel16aefdb2012-05-30 10:41:23 -0700504 mutex_lock(&drvdata->mutex);
505 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800506
Pratik Patel16aefdb2012-05-30 10:41:23 -0700507 if (drvdata->mode & ETM_MODE_EXCLUDE)
508 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800509 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700510 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800511
Pratik Patel16aefdb2012-05-30 10:41:23 -0700512 if (drvdata->mode & ETM_MODE_CYCACC)
513 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800514 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700515 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800516
Pratik Patel16aefdb2012-05-30 10:41:23 -0700517 if (drvdata->mode & ETM_MODE_STALL)
518 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800519 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700520 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800521
Pratik Patel16aefdb2012-05-30 10:41:23 -0700522 if (drvdata->mode & ETM_MODE_TIMESTAMP)
523 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800524 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700525 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700526
Pratik Patel16aefdb2012-05-30 10:41:23 -0700527 if (drvdata->mode & ETM_MODE_CTXID)
528 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800529 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700530 drvdata->ctrl &= ~(BIT(14) | BIT(15));
531 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800532
Pratik Patela9c0e062012-05-28 13:45:35 -0700533 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800534}
Pratik Patela9c0e062012-05-28 13:45:35 -0700535static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800536
Pratik Patela9c0e062012-05-28 13:45:35 -0700537static ssize_t etm_show_trigger_event(struct device *dev,
538 struct device_attribute *attr, char *buf)
539{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700540 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700541 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700542
Pratik Patela9c0e062012-05-28 13:45:35 -0700543 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
544}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800545
Pratik Patela9c0e062012-05-28 13:45:35 -0700546static ssize_t etm_store_trigger_event(struct device *dev,
547 struct device_attribute *attr,
548 const char *buf, size_t size)
549{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700550 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700551 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800552
Pratik Patela9c0e062012-05-28 13:45:35 -0700553 if (sscanf(buf, "%lx", &val) != 1)
554 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800555
Pratik Patel16aefdb2012-05-30 10:41:23 -0700556 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700557 return size;
558}
559static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
560 etm_store_trigger_event);
561
562static ssize_t etm_show_enable_event(struct device *dev,
563 struct device_attribute *attr, char *buf)
564{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700565 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700566 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700567
Pratik Patela9c0e062012-05-28 13:45:35 -0700568 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
569}
570
571static ssize_t etm_store_enable_event(struct device *dev,
572 struct device_attribute *attr,
573 const char *buf, size_t size)
574{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700575 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700576 unsigned long val;
577
578 if (sscanf(buf, "%lx", &val) != 1)
579 return -EINVAL;
580
Pratik Patel16aefdb2012-05-30 10:41:23 -0700581 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700582 return size;
583}
584static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
585 etm_store_enable_event);
586
587static ssize_t etm_show_fifofull_level(struct device *dev,
588 struct device_attribute *attr, char *buf)
589{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700590 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700591 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700592
Pratik Patela9c0e062012-05-28 13:45:35 -0700593 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
594}
595
596static ssize_t etm_store_fifofull_level(struct device *dev,
597 struct device_attribute *attr,
598 const char *buf, size_t size)
599{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700600 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700601 unsigned long val;
602
603 if (sscanf(buf, "%lx", &val) != 1)
604 return -EINVAL;
605
Pratik Patel16aefdb2012-05-30 10:41:23 -0700606 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700607 return size;
608}
609static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
610 etm_store_fifofull_level);
611
612static ssize_t etm_show_addr_idx(struct device *dev,
613 struct device_attribute *attr, char *buf)
614{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700615 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700616 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700617
Pratik Patela9c0e062012-05-28 13:45:35 -0700618 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
619}
620
621static ssize_t etm_store_addr_idx(struct device *dev,
622 struct device_attribute *attr,
623 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800624{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700625 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800626 unsigned long val;
627
628 if (sscanf(buf, "%lx", &val) != 1)
629 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700630 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800631 return -EINVAL;
632
633 /* Use mutex to ensure index doesn't change while it gets dereferenced
634 * multiple times within a mutex block elsewhere.
635 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700636 mutex_lock(&drvdata->mutex);
637 drvdata->addr_idx = val;
638 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700639 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800640}
Pratik Patela9c0e062012-05-28 13:45:35 -0700641static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
642 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800643
Pratik Patela9c0e062012-05-28 13:45:35 -0700644static ssize_t etm_show_addr_single(struct device *dev,
645 struct device_attribute *attr, char *buf)
646{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700647 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700648 unsigned long val;
649 uint8_t idx;
650
Pratik Patel16aefdb2012-05-30 10:41:23 -0700651 mutex_lock(&drvdata->mutex);
652 idx = drvdata->addr_idx;
653 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
654 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
655 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700656 return -EPERM;
657 }
658
Pratik Patel16aefdb2012-05-30 10:41:23 -0700659 val = drvdata->addr_val[idx];
660 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700661 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
662}
663
664static ssize_t etm_store_addr_single(struct device *dev,
665 struct device_attribute *attr,
666 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800667{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700668 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800669 unsigned long val;
670 uint8_t idx;
671
672 if (sscanf(buf, "%lx", &val) != 1)
673 return -EINVAL;
674
Pratik Patel16aefdb2012-05-30 10:41:23 -0700675 mutex_lock(&drvdata->mutex);
676 idx = drvdata->addr_idx;
677 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
678 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
679 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800680 return -EPERM;
681 }
682
Pratik Patel16aefdb2012-05-30 10:41:23 -0700683 drvdata->addr_val[idx] = val;
684 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
685 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700686 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800687}
Pratik Patela9c0e062012-05-28 13:45:35 -0700688static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
689 etm_store_addr_single);
690
691static ssize_t etm_show_addr_range(struct device *dev,
692 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800693{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700694 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700695 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800696 uint8_t idx;
697
Pratik Patel16aefdb2012-05-30 10:41:23 -0700698 mutex_lock(&drvdata->mutex);
699 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700700 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700701 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700702 return -EPERM;
703 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700704 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
705 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
706 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
707 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
708 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800709 return -EPERM;
710 }
711
Pratik Patel16aefdb2012-05-30 10:41:23 -0700712 val1 = drvdata->addr_val[idx];
713 val2 = drvdata->addr_val[idx + 1];
714 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700715 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800716}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800717
Pratik Patela9c0e062012-05-28 13:45:35 -0700718static ssize_t etm_store_addr_range(struct device *dev,
719 struct device_attribute *attr,
720 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800721{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700722 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800723 unsigned long val1, val2;
724 uint8_t idx;
725
726 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
727 return -EINVAL;
728 /* lower address comparator cannot have a higher address value */
729 if (val1 > val2)
730 return -EINVAL;
731
Pratik Patel16aefdb2012-05-30 10:41:23 -0700732 mutex_lock(&drvdata->mutex);
733 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800734 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700735 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800736 return -EPERM;
737 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700738 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
739 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
740 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
741 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
742 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800743 return -EPERM;
744 }
745
Pratik Patel16aefdb2012-05-30 10:41:23 -0700746 drvdata->addr_val[idx] = val1;
747 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
748 drvdata->addr_val[idx + 1] = val2;
749 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
750 drvdata->enable_ctrl1 |= (1 << (idx/2));
751 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700752 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800753}
Pratik Patela9c0e062012-05-28 13:45:35 -0700754static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
755 etm_store_addr_range);
756
757static ssize_t etm_show_addr_start(struct device *dev,
758 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800759{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700760 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700761 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800762 uint8_t idx;
763
Pratik Patel16aefdb2012-05-30 10:41:23 -0700764 mutex_lock(&drvdata->mutex);
765 idx = drvdata->addr_idx;
766 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
767 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
768 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800769 return -EPERM;
770 }
771
Pratik Patel16aefdb2012-05-30 10:41:23 -0700772 val = drvdata->addr_val[idx];
773 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700774 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800775}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800776
Pratik Patela9c0e062012-05-28 13:45:35 -0700777static ssize_t etm_store_addr_start(struct device *dev,
778 struct device_attribute *attr,
779 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800780{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700781 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800782 unsigned long val;
783 uint8_t idx;
784
785 if (sscanf(buf, "%lx", &val) != 1)
786 return -EINVAL;
787
Pratik Patel16aefdb2012-05-30 10:41:23 -0700788 mutex_lock(&drvdata->mutex);
789 idx = drvdata->addr_idx;
790 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
791 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
792 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800793 return -EPERM;
794 }
795
Pratik Patel16aefdb2012-05-30 10:41:23 -0700796 drvdata->addr_val[idx] = val;
797 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
798 drvdata->startstop_ctrl |= (1 << idx);
799 drvdata->enable_ctrl1 |= BIT(25);
800 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700801 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800802}
Pratik Patela9c0e062012-05-28 13:45:35 -0700803static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
804 etm_store_addr_start);
805
806static ssize_t etm_show_addr_stop(struct device *dev,
807 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800808{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700809 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800810 unsigned long val;
811 uint8_t idx;
812
Pratik Patel16aefdb2012-05-30 10:41:23 -0700813 mutex_lock(&drvdata->mutex);
814 idx = drvdata->addr_idx;
815 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
816 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
817 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800818 return -EPERM;
819 }
820
Pratik Patel16aefdb2012-05-30 10:41:23 -0700821 val = drvdata->addr_val[idx];
822 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800823 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
824}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800825
Pratik Patela9c0e062012-05-28 13:45:35 -0700826static ssize_t etm_store_addr_stop(struct device *dev,
827 struct device_attribute *attr,
828 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800829{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700830 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800831 unsigned long val;
832 uint8_t idx;
833
834 if (sscanf(buf, "%lx", &val) != 1)
835 return -EINVAL;
836
Pratik Patel16aefdb2012-05-30 10:41:23 -0700837 mutex_lock(&drvdata->mutex);
838 idx = drvdata->addr_idx;
839 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
840 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
841 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800842 return -EPERM;
843 }
844
Pratik Patel16aefdb2012-05-30 10:41:23 -0700845 drvdata->addr_val[idx] = val;
846 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
847 drvdata->startstop_ctrl |= (1 << (idx + 16));
848 drvdata->enable_ctrl1 |= BIT(25);
849 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700850 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800851}
Pratik Patela9c0e062012-05-28 13:45:35 -0700852static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
853 etm_store_addr_stop);
854
855static ssize_t etm_show_addr_acctype(struct device *dev,
856 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800857{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700858 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800859 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800860
Pratik Patel16aefdb2012-05-30 10:41:23 -0700861 mutex_lock(&drvdata->mutex);
862 val = drvdata->addr_acctype[drvdata->addr_idx];
863 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800864 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
865}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800866
Pratik Patela9c0e062012-05-28 13:45:35 -0700867static ssize_t etm_store_addr_acctype(struct device *dev,
868 struct device_attribute *attr,
869 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800870{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700871 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800872 unsigned long val;
873
874 if (sscanf(buf, "%lx", &val) != 1)
875 return -EINVAL;
876
Pratik Patel16aefdb2012-05-30 10:41:23 -0700877 mutex_lock(&drvdata->mutex);
878 drvdata->addr_acctype[drvdata->addr_idx] = val;
879 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700880 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800881}
Pratik Patela9c0e062012-05-28 13:45:35 -0700882static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
883 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800884
Pratik Patela9c0e062012-05-28 13:45:35 -0700885static ssize_t etm_show_cntr_idx(struct device *dev,
886 struct device_attribute *attr, char *buf)
887{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700888 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700889 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700890
Pratik Patel6630ebe2012-03-06 16:44:22 -0800891 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
892}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800893
Pratik Patela9c0e062012-05-28 13:45:35 -0700894static ssize_t etm_store_cntr_idx(struct device *dev,
895 struct device_attribute *attr,
896 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800897{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700898 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800899 unsigned long val;
900
901 if (sscanf(buf, "%lx", &val) != 1)
902 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700903 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800904 return -EINVAL;
905
906 /* Use mutex to ensure index doesn't change while it gets dereferenced
907 * multiple times within a mutex block elsewhere.
908 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700909 mutex_lock(&drvdata->mutex);
910 drvdata->cntr_idx = val;
911 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700912 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800913}
Pratik Patela9c0e062012-05-28 13:45:35 -0700914static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
915 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800916
Pratik Patela9c0e062012-05-28 13:45:35 -0700917static ssize_t etm_show_cntr_rld_val(struct device *dev,
918 struct device_attribute *attr, char *buf)
919{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700920 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700921 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700922
Pratik Patel16aefdb2012-05-30 10:41:23 -0700923 mutex_lock(&drvdata->mutex);
924 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
925 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700926 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
927}
928
929static ssize_t etm_store_cntr_rld_val(struct device *dev,
930 struct device_attribute *attr,
931 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800932{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700933 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800934 unsigned long val;
935
936 if (sscanf(buf, "%lx", &val) != 1)
937 return -EINVAL;
938
Pratik Patel16aefdb2012-05-30 10:41:23 -0700939 mutex_lock(&drvdata->mutex);
940 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
941 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700942 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800943}
Pratik Patela9c0e062012-05-28 13:45:35 -0700944static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
945 etm_store_cntr_rld_val);
946
947static ssize_t etm_show_cntr_event(struct device *dev,
948 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800949{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700950 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800951 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700952
Pratik Patel16aefdb2012-05-30 10:41:23 -0700953 mutex_lock(&drvdata->mutex);
954 val = drvdata->cntr_event[drvdata->cntr_idx];
955 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800956 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
957}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800958
Pratik Patela9c0e062012-05-28 13:45:35 -0700959static ssize_t etm_store_cntr_event(struct device *dev,
960 struct device_attribute *attr,
961 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800962{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700963 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800964 unsigned long val;
965
966 if (sscanf(buf, "%lx", &val) != 1)
967 return -EINVAL;
968
Pratik Patel16aefdb2012-05-30 10:41:23 -0700969 mutex_lock(&drvdata->mutex);
970 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
971 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700972 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800973}
Pratik Patela9c0e062012-05-28 13:45:35 -0700974static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
975 etm_store_cntr_event);
976
977static ssize_t etm_show_cntr_rld_event(struct device *dev,
978 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800979{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700980 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800981 unsigned long val;
982
Pratik Patel16aefdb2012-05-30 10:41:23 -0700983 mutex_lock(&drvdata->mutex);
984 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
985 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800986 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
987}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800988
Pratik Patela9c0e062012-05-28 13:45:35 -0700989static ssize_t etm_store_cntr_rld_event(struct device *dev,
990 struct device_attribute *attr,
991 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800992{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700993 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800994 unsigned long val;
995
996 if (sscanf(buf, "%lx", &val) != 1)
997 return -EINVAL;
998
Pratik Patel16aefdb2012-05-30 10:41:23 -0700999 mutex_lock(&drvdata->mutex);
1000 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1001 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001002 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001003}
Pratik Patela9c0e062012-05-28 13:45:35 -07001004static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1005 etm_store_cntr_rld_event);
1006
1007static ssize_t etm_show_cntr_val(struct device *dev,
1008 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001009{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001010 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001011 unsigned long val;
1012
Pratik Patel16aefdb2012-05-30 10:41:23 -07001013 mutex_lock(&drvdata->mutex);
1014 val = drvdata->cntr_val[drvdata->cntr_idx];
1015 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001016 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1017}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001018
Pratik Patela9c0e062012-05-28 13:45:35 -07001019static ssize_t etm_store_cntr_val(struct device *dev,
1020 struct device_attribute *attr,
1021 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001022{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001023 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001024 unsigned long val;
1025
1026 if (sscanf(buf, "%lx", &val) != 1)
1027 return -EINVAL;
1028
Pratik Patel16aefdb2012-05-30 10:41:23 -07001029 mutex_lock(&drvdata->mutex);
1030 drvdata->cntr_val[drvdata->cntr_idx] = val;
1031 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001032 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001033}
Pratik Patela9c0e062012-05-28 13:45:35 -07001034static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1035 etm_store_cntr_val);
1036
1037static ssize_t etm_show_seq_12_event(struct device *dev,
1038 struct device_attribute *attr, char *buf)
1039{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001040 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001041 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001042
Pratik Patela9c0e062012-05-28 13:45:35 -07001043 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1044}
1045
1046static ssize_t etm_store_seq_12_event(struct device *dev,
1047 struct device_attribute *attr,
1048 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001049{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001050 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001051 unsigned long val;
1052
Pratik Patela9c0e062012-05-28 13:45:35 -07001053 if (sscanf(buf, "%lx", &val) != 1)
1054 return -EINVAL;
1055
Pratik Patel16aefdb2012-05-30 10:41:23 -07001056 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001057 return size;
1058}
1059static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1060 etm_store_seq_12_event);
1061
1062static ssize_t etm_show_seq_21_event(struct device *dev,
1063 struct device_attribute *attr, char *buf)
1064{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001065 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001066 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001067
Pratik Patel6630ebe2012-03-06 16:44:22 -08001068 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1069}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001070
Pratik Patela9c0e062012-05-28 13:45:35 -07001071static ssize_t etm_store_seq_21_event(struct device *dev,
1072 struct device_attribute *attr,
1073 const char *buf, size_t size)
1074{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001075 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001076 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001077
Pratik Patela9c0e062012-05-28 13:45:35 -07001078 if (sscanf(buf, "%lx", &val) != 1)
1079 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001080
Pratik Patel16aefdb2012-05-30 10:41:23 -07001081 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001082 return size;
1083}
1084static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1085 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001086
Pratik Patela9c0e062012-05-28 13:45:35 -07001087static ssize_t etm_show_seq_23_event(struct device *dev,
1088 struct device_attribute *attr, char *buf)
1089{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001090 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001091 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001092
Pratik Patela9c0e062012-05-28 13:45:35 -07001093 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1094}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001095
Pratik Patela9c0e062012-05-28 13:45:35 -07001096static ssize_t etm_store_seq_23_event(struct device *dev,
1097 struct device_attribute *attr,
1098 const char *buf, size_t size)
1099{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001100 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001101 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001102
Pratik Patela9c0e062012-05-28 13:45:35 -07001103 if (sscanf(buf, "%lx", &val) != 1)
1104 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001105
Pratik Patel16aefdb2012-05-30 10:41:23 -07001106 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001107 return size;
1108}
1109static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1110 etm_store_seq_23_event);
1111
1112static ssize_t etm_show_seq_31_event(struct device *dev,
1113 struct device_attribute *attr, char *buf)
1114{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001115 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001116 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001117
Pratik Patela9c0e062012-05-28 13:45:35 -07001118 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1119}
1120
1121static ssize_t etm_store_seq_31_event(struct device *dev,
1122 struct device_attribute *attr,
1123 const char *buf, size_t size)
1124{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001125 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001126 unsigned long val;
1127
1128 if (sscanf(buf, "%lx", &val) != 1)
1129 return -EINVAL;
1130
Pratik Patel16aefdb2012-05-30 10:41:23 -07001131 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001132 return size;
1133}
1134static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1135 etm_store_seq_31_event);
1136
1137static ssize_t etm_show_seq_32_event(struct device *dev,
1138 struct device_attribute *attr, char *buf)
1139{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001140 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001141 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001142
Pratik Patela9c0e062012-05-28 13:45:35 -07001143 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1144}
1145
1146static ssize_t etm_store_seq_32_event(struct device *dev,
1147 struct device_attribute *attr,
1148 const char *buf, size_t size)
1149{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001150 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001151 unsigned long val;
1152
1153 if (sscanf(buf, "%lx", &val) != 1)
1154 return -EINVAL;
1155
Pratik Patel16aefdb2012-05-30 10:41:23 -07001156 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001157 return size;
1158}
1159static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1160 etm_store_seq_32_event);
1161
1162static ssize_t etm_show_seq_13_event(struct device *dev,
1163 struct device_attribute *attr, char *buf)
1164{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001165 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001166 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001167
Pratik Patela9c0e062012-05-28 13:45:35 -07001168 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1169}
1170
1171static ssize_t etm_store_seq_13_event(struct device *dev,
1172 struct device_attribute *attr,
1173 const char *buf, size_t size)
1174{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001175 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001176 unsigned long val;
1177
1178 if (sscanf(buf, "%lx", &val) != 1)
1179 return -EINVAL;
1180
Pratik Patel16aefdb2012-05-30 10:41:23 -07001181 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001182 return size;
1183}
1184static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1185 etm_store_seq_13_event);
1186
1187static ssize_t etm_show_seq_curr_state(struct device *dev,
1188 struct device_attribute *attr, char *buf)
1189{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001190 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001191 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001192
Pratik Patela9c0e062012-05-28 13:45:35 -07001193 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1194}
1195
1196static ssize_t etm_store_seq_curr_state(struct device *dev,
1197 struct device_attribute *attr,
1198 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001199{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001200 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001201 unsigned long val;
1202
1203 if (sscanf(buf, "%lx", &val) != 1)
1204 return -EINVAL;
1205 if (val > ETM_SEQ_STATE_MAX_VAL)
1206 return -EINVAL;
1207
Pratik Patel16aefdb2012-05-30 10:41:23 -07001208 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001209 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001210}
Pratik Patela9c0e062012-05-28 13:45:35 -07001211static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1212 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001213
Pratik Patela9c0e062012-05-28 13:45:35 -07001214static ssize_t etm_show_ctxid_idx(struct device *dev,
1215 struct device_attribute *attr, char *buf)
1216{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001217 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001218 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001219
Pratik Patela9c0e062012-05-28 13:45:35 -07001220 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1221}
1222
1223static ssize_t etm_store_ctxid_idx(struct device *dev,
1224 struct device_attribute *attr,
1225 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001226{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001227 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001228 unsigned long val;
1229
1230 if (sscanf(buf, "%lx", &val) != 1)
1231 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001232 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001233 return -EINVAL;
1234
1235 /* Use mutex to ensure index doesn't change while it gets dereferenced
1236 * multiple times within a mutex block elsewhere.
1237 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001238 mutex_lock(&drvdata->mutex);
1239 drvdata->ctxid_idx = val;
1240 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001241 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001242}
Pratik Patela9c0e062012-05-28 13:45:35 -07001243static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1244 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001245
Pratik Patela9c0e062012-05-28 13:45:35 -07001246static ssize_t etm_show_ctxid_val(struct device *dev,
1247 struct device_attribute *attr, char *buf)
1248{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001249 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001250 unsigned long val;
1251
Pratik Patel16aefdb2012-05-30 10:41:23 -07001252 mutex_lock(&drvdata->mutex);
1253 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1254 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001255 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1256}
1257
1258static ssize_t etm_store_ctxid_val(struct device *dev,
1259 struct device_attribute *attr,
1260 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001261{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001262 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001263 unsigned long val;
1264
1265 if (sscanf(buf, "%lx", &val) != 1)
1266 return -EINVAL;
1267
Pratik Patel16aefdb2012-05-30 10:41:23 -07001268 mutex_lock(&drvdata->mutex);
1269 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1270 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001271 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001272}
Pratik Patela9c0e062012-05-28 13:45:35 -07001273static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1274 etm_store_ctxid_val);
1275
1276static ssize_t etm_show_ctxid_mask(struct device *dev,
1277 struct device_attribute *attr, char *buf)
1278{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001279 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001280 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001281
Pratik Patela9c0e062012-05-28 13:45:35 -07001282 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1283}
1284
1285static ssize_t etm_store_ctxid_mask(struct device *dev,
1286 struct device_attribute *attr,
1287 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001288{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001289 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001290 unsigned long val;
1291
Pratik Patela9c0e062012-05-28 13:45:35 -07001292 if (sscanf(buf, "%lx", &val) != 1)
1293 return -EINVAL;
1294
Pratik Patel16aefdb2012-05-30 10:41:23 -07001295 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001296 return size;
1297}
1298static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1299 etm_store_ctxid_mask);
1300
1301static ssize_t etm_show_sync_freq(struct device *dev,
1302 struct device_attribute *attr, char *buf)
1303{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001304 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001305 unsigned long val = drvdata->sync_freq;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001306 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1307}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001308
Pratik Patela9c0e062012-05-28 13:45:35 -07001309static ssize_t etm_store_sync_freq(struct device *dev,
1310 struct device_attribute *attr,
1311 const char *buf, size_t size)
1312{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001313 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001314 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001315
Pratik Patela9c0e062012-05-28 13:45:35 -07001316 if (sscanf(buf, "%lx", &val) != 1)
1317 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001318
Pratik Patel16aefdb2012-05-30 10:41:23 -07001319 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001320 return size;
1321}
1322static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1323 etm_store_sync_freq);
1324
1325static ssize_t etm_show_timestamp_event(struct device *dev,
1326 struct device_attribute *attr,
1327 char *buf)
1328{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001329 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001330 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001331
Pratik Patela9c0e062012-05-28 13:45:35 -07001332 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1333}
1334
1335static ssize_t etm_store_timestamp_event(struct device *dev,
1336 struct device_attribute *attr,
1337 const char *buf, size_t size)
1338{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001339 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001340 unsigned long val;
1341
1342 if (sscanf(buf, "%lx", &val) != 1)
1343 return -EINVAL;
1344
Pratik Patel16aefdb2012-05-30 10:41:23 -07001345 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001346 return size;
1347}
1348static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1349 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001350
1351static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001352 &dev_attr_nr_addr_cmp.attr,
1353 &dev_attr_nr_cntr.attr,
1354 &dev_attr_nr_ctxid_cmp.attr,
1355 &dev_attr_reset.attr,
1356 &dev_attr_mode.attr,
1357 &dev_attr_trigger_event.attr,
1358 &dev_attr_enable_event.attr,
1359 &dev_attr_fifofull_level.attr,
1360 &dev_attr_addr_idx.attr,
1361 &dev_attr_addr_single.attr,
1362 &dev_attr_addr_range.attr,
1363 &dev_attr_addr_start.attr,
1364 &dev_attr_addr_stop.attr,
1365 &dev_attr_addr_acctype.attr,
1366 &dev_attr_cntr_idx.attr,
1367 &dev_attr_cntr_rld_val.attr,
1368 &dev_attr_cntr_event.attr,
1369 &dev_attr_cntr_rld_event.attr,
1370 &dev_attr_cntr_val.attr,
1371 &dev_attr_seq_12_event.attr,
1372 &dev_attr_seq_21_event.attr,
1373 &dev_attr_seq_23_event.attr,
1374 &dev_attr_seq_31_event.attr,
1375 &dev_attr_seq_32_event.attr,
1376 &dev_attr_seq_13_event.attr,
1377 &dev_attr_seq_curr_state.attr,
1378 &dev_attr_ctxid_idx.attr,
1379 &dev_attr_ctxid_val.attr,
1380 &dev_attr_ctxid_mask.attr,
1381 &dev_attr_sync_freq.attr,
1382 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001383 NULL,
1384};
1385
1386static struct attribute_group etm_attr_grp = {
1387 .attrs = etm_attrs,
1388};
1389
Pratik Patel3b0ca882012-06-01 16:54:14 -07001390static const struct attribute_group *etm_attr_grps[] = {
1391 &etm_attr_grp,
1392 NULL,
1393};
1394
1395/* Memory mapped writes to clear os lock not supported */
1396static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001397{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001398 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001399
Pratik Patel3b0ca882012-06-01 16:54:14 -07001400 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1401 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001402}
1403
Stephen Boyda9510502012-04-24 16:23:34 -07001404static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001405{
Pratik Patel61de7302012-03-07 12:06:10 -08001406 switch (arch) {
1407 case PFT_ARCH_V1_1:
1408 break;
1409 default:
1410 return false;
1411 }
1412 return true;
1413}
1414
Pratik Patel3b0ca882012-06-01 16:54:14 -07001415static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
Pratik Patel61de7302012-03-07 12:06:10 -08001416{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001417 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -08001418 uint32_t etmidr;
1419 uint32_t etmccr;
Pratik Patel7831c082011-06-08 21:44:37 -07001420
Pratik Patel17f3b822011-11-21 12:41:47 -08001421 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel492b3012012-03-06 14:22:30 -08001422 etm_os_unlock(NULL);
1423 smp_call_function(etm_os_unlock, NULL, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001424 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001425 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001426 etm_clr_pwrdwn(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001427 /* Set prog bit. It will be set from reset but this is included to
1428 * ensure it is set
1429 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001430 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001431
1432 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001433 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001434 drvdata->arch = BMVAL(etmidr, 4, 11);
1435 if (etm_arch_supported(drvdata->arch) == false) {
Pratik Patel61de7302012-03-07 12:06:10 -08001436 ret = -EINVAL;
1437 goto err;
1438 }
Pratik Patel7831c082011-06-08 21:44:37 -07001439
Pratik Patel3b0ca882012-06-01 16:54:14 -07001440 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001441 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1442 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1443 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1444 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1445 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001446
Pratik Patel17f3b822011-11-21 12:41:47 -08001447 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001448 etm_set_pwrdwn(drvdata);
1449 ETM_LOCK(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001450
1451 return 0;
1452err:
1453 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001454}
1455
Pratik Patelc14b4df2012-09-05 18:07:59 -07001456static void __devinit etm_copy_arch_data(struct etm_drvdata *drvdata)
1457{
1458 drvdata->arch = etm0drvdata->arch;
1459 drvdata->nr_addr_cmp = etm0drvdata->nr_addr_cmp;
1460 drvdata->nr_cntr = etm0drvdata->nr_cntr;
1461 drvdata->nr_ext_inp = etm0drvdata->nr_ext_inp;
1462 drvdata->nr_ext_out = etm0drvdata->nr_ext_out;
1463 drvdata->nr_ctxid_cmp = etm0drvdata->nr_ctxid_cmp;
1464}
1465
Pratik Patel3b0ca882012-06-01 16:54:14 -07001466static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001467{
1468 int i;
1469
1470 drvdata->trigger_event = 0x406F;
1471 drvdata->enable_event = 0x6F;
1472 drvdata->enable_ctrl1 = 0x1;
1473 drvdata->fifofull_level = 0x28;
1474 if (drvdata->nr_addr_cmp >= 2) {
1475 drvdata->addr_val[0] = (uint32_t) _stext;
1476 drvdata->addr_val[1] = (uint32_t) _etext;
1477 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1478 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1479 }
1480 for (i = 0; i < drvdata->nr_cntr; i++) {
1481 drvdata->cntr_event[i] = 0x406F;
1482 drvdata->cntr_rld_event[i] = 0x406F;
1483 }
1484 drvdata->seq_12_event = 0x406F;
1485 drvdata->seq_21_event = 0x406F;
1486 drvdata->seq_23_event = 0x406F;
1487 drvdata->seq_31_event = 0x406F;
1488 drvdata->seq_32_event = 0x406F;
1489 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001490 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1491 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1492 drvdata->sync_freq = 0x100;
1493 else
1494 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001495 drvdata->timestamp_event = 0x406F;
1496
1497 /* Overrides for Krait pass1 */
1498 if (cpu_is_krait_v1()) {
1499 /* Krait pass1 doesn't support include filtering and non-cycle
1500 * accurate tracing
1501 */
1502 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1503 drvdata->ctrl = 0x1000;
1504 drvdata->enable_ctrl1 = 0x1000000;
1505 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1506 drvdata->addr_val[i] = 0x0;
1507 drvdata->addr_acctype[i] = 0x0;
1508 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1509 }
1510 }
1511}
1512
Pratik Patel492b3012012-03-06 14:22:30 -08001513static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001514{
Pratik Patele5771792011-09-17 18:33:54 -07001515 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001516 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001517 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001518 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001519 struct resource *res;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001520 static int etm_count;
1521 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001522
Pratik Patel670627c2012-08-19 13:50:51 -07001523 /* Fail probe for Krait pass3 until supported */
1524 if (cpu_is_krait_v3()) {
1525 dev_info(dev, "ETM: failing probe for Krait pass3\n");
1526 return -EINVAL;
1527 }
1528
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001529 if (pdev->dev.of_node) {
1530 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1531 if (IS_ERR(pdata))
1532 return PTR_ERR(pdata);
1533 pdev->dev.platform_data = pdata;
1534 }
1535
Pratik Patel4a1b2522012-06-17 15:31:15 -07001536 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1537 if (!drvdata)
1538 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001539 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001540 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001541
Pratik Patel4a1b2522012-06-17 15:31:15 -07001542 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1543 if (!res)
1544 return -ENODEV;
Pratik Patel2c09b762012-07-21 15:54:54 -07001545
Pratik Patel4a1b2522012-06-17 15:31:15 -07001546 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1547 if (!drvdata->base)
1548 return -ENOMEM;
1549
Pratik Patel16aefdb2012-05-30 10:41:23 -07001550 mutex_init(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001551 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patele10a77c2012-03-20 10:35:16 -07001552
Pratik Patel4a1b2522012-06-17 15:31:15 -07001553 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001554 if (IS_ERR(drvdata->clk)) {
1555 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001556 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001557 }
Pratik Patel2c09b762012-07-21 15:54:54 -07001558
Pratik Patel6fb38342012-06-03 14:51:38 -07001559 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001560 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001561 goto err0;
1562
1563 drvdata->cpu = etm_count++;
1564
Pratik Patel16aefdb2012-05-30 10:41:23 -07001565 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001566 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001567 goto err0;
Pratik Patel2c09b762012-07-21 15:54:54 -07001568
Pratik Patelc14b4df2012-09-05 18:07:59 -07001569 /* Use CPU0 to populate read-only configuration data for ETM0. For other
1570 * ETMs copy it over from ETM0.
1571 */
1572 if (drvdata->cpu == 0) {
1573 ret = etm_init_arch_data(drvdata);
1574 if (ret)
1575 goto err1;
1576 etm0drvdata = drvdata;
1577 } else {
1578 if (etm0drvdata)
1579 etm_copy_arch_data(drvdata);
1580 else
1581 goto err1;
1582 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001583 etm_init_default_data(drvdata);
Pratik Patel2c09b762012-07-21 15:54:54 -07001584
Pratik Patel16aefdb2012-05-30 10:41:23 -07001585 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001586
Pratik Patel4a1b2522012-06-17 15:31:15 -07001587 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001588 if (!desc) {
1589 ret = -ENOMEM;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001590 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001591 }
1592 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1593 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1594 desc->ops = &etm_cs_ops;
1595 desc->pdata = pdev->dev.platform_data;
1596 desc->dev = &pdev->dev;
1597 desc->groups = etm_attr_grps;
1598 desc->owner = THIS_MODULE;
1599 drvdata->csdev = coresight_register(desc);
1600 if (IS_ERR(drvdata->csdev)) {
1601 ret = PTR_ERR(drvdata->csdev);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001602 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001603 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001604
Pratik Patel4a1b2522012-06-17 15:31:15 -07001605 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001606
Pratik Patel3b0ca882012-06-01 16:54:14 -07001607 if (boot_enable)
1608 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001609
1610 return 0;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001611err1:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001612 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001613err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001614 wake_lock_destroy(&drvdata->wake_lock);
1615 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001616 return ret;
1617}
1618
Pratik Patelf6fe9182012-03-20 14:04:18 -07001619static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001620{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001621 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1622
1623 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001624 wake_lock_destroy(&drvdata->wake_lock);
1625 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001626 return 0;
1627}
1628
Pratik Patel9eae4822012-05-14 17:34:53 -07001629static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001630 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001631 {}
1632};
1633
Pratik Patel492b3012012-03-06 14:22:30 -08001634static struct platform_driver etm_driver = {
1635 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001636 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001637 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001638 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001639 .owner = THIS_MODULE,
1640 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001641 },
1642};
1643
Pratik Patel492b3012012-03-06 14:22:30 -08001644int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001645{
Pratik Patel492b3012012-03-06 14:22:30 -08001646 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001647}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001648module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001649
Pratik Patelf6fe9182012-03-20 14:04:18 -07001650void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001651{
Pratik Patel492b3012012-03-06 14:22:30 -08001652 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001653}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001654module_exit(etm_exit);
1655
1656MODULE_LICENSE("GPL v2");
1657MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");