blob: ed4a783c6cca1c7a9aa2c8e540e6ce281bc4bd79 [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
39#define etm_writel(drvdata, val, off) \
40 __raw_writel((val), drvdata->base + off)
41#define etm_readl(drvdata, off) \
42 __raw_readl(drvdata->base + off)
43
44#define ETM_LOCK(drvdata) \
45do { \
46 mb(); \
47 etm_writel(drvdata, 0x0, CORESIGHT_LAR); \
48} while (0)
49#define ETM_UNLOCK(drvdata) \
50do { \
51 etm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
52 mb(); \
53} while (0)
54
Pratik Patel7831c082011-06-08 21:44:37 -070055
56/*
57 * Device registers:
58 * 0x000 - 0x2FC: Trace registers
59 * 0x300 - 0x314: Management registers
60 * 0x318 - 0xEFC: Trace registers
61 *
62 * Coresight registers
63 * 0xF00 - 0xF9C: Management registers
64 * 0xFA0 - 0xFA4: Management registers in PFTv1.0
65 * Trace registers in PFTv1.1
66 * 0xFA8 - 0xFFC: Management registers
67 */
68
69/* Trace registers (0x000-0x2FC) */
70#define ETMCR (0x000)
71#define ETMCCR (0x004)
72#define ETMTRIGGER (0x008)
73#define ETMSR (0x010)
74#define ETMSCR (0x014)
75#define ETMTSSCR (0x018)
76#define ETMTEEVR (0x020)
77#define ETMTECR1 (0x024)
78#define ETMFFLR (0x02C)
79#define ETMACVRn(n) (0x040 + (n * 4))
80#define ETMACTRn(n) (0x080 + (n * 4))
81#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
82#define ETMCNTENRn(n) (0x150 + (n * 4))
83#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
84#define ETMCNTVRn(n) (0x170 + (n * 4))
85#define ETMSQ12EVR (0x180)
86#define ETMSQ21EVR (0x184)
87#define ETMSQ23EVR (0x188)
Pratik Pateld5bbc762012-01-29 14:13:21 -080088#define ETMSQ31EVR (0x18C)
89#define ETMSQ32EVR (0x190)
90#define ETMSQ13EVR (0x194)
Pratik Patel7831c082011-06-08 21:44:37 -070091#define ETMSQR (0x19C)
92#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
93#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
94#define ETMCIDCMR (0x1BC)
95#define ETMIMPSPEC0 (0x1C0)
96#define ETMIMPSPEC1 (0x1C4)
97#define ETMIMPSPEC2 (0x1C8)
98#define ETMIMPSPEC3 (0x1CC)
99#define ETMIMPSPEC4 (0x1D0)
100#define ETMIMPSPEC5 (0x1D4)
101#define ETMIMPSPEC6 (0x1D8)
102#define ETMIMPSPEC7 (0x1DC)
103#define ETMSYNCFR (0x1E0)
104#define ETMIDR (0x1E4)
105#define ETMCCER (0x1E8)
106#define ETMEXTINSELR (0x1EC)
107#define ETMTESSEICR (0x1F0)
108#define ETMEIBCR (0x1F4)
109#define ETMTSEVR (0x1F8)
110#define ETMAUXCR (0x1FC)
111#define ETMTRACEIDR (0x200)
Pratik Pateld5bbc762012-01-29 14:13:21 -0800112#define ETMVMIDCVR (0x240)
Pratik Patel7831c082011-06-08 21:44:37 -0700113/* Management registers (0x300-0x314) */
114#define ETMOSLAR (0x300)
115#define ETMOSLSR (0x304)
116#define ETMOSSRR (0x308)
117#define ETMPDCR (0x310)
118#define ETMPDSR (0x314)
119
Pratik Patel3b0ca882012-06-01 16:54:14 -0700120
Pratik Patel61de7302012-03-07 12:06:10 -0800121#define ETM_MAX_ADDR_CMP (16)
122#define ETM_MAX_CNTR (4)
123#define ETM_MAX_CTXID_CMP (3)
124
Pratik Patel6630ebe2012-03-06 16:44:22 -0800125#define ETM_MODE_EXCLUDE BIT(0)
126#define ETM_MODE_CYCACC BIT(1)
127#define ETM_MODE_STALL BIT(2)
128#define ETM_MODE_TIMESTAMP BIT(3)
129#define ETM_MODE_CTXID BIT(4)
130#define ETM_MODE_ALL (0x1F)
131
132#define ETM_EVENT_MASK (0x1FFFF)
133#define ETM_SYNC_MASK (0xFFF)
134#define ETM_ALL_MASK (0xFFFFFFFF)
135
136#define ETM_SEQ_STATE_MAX_VAL (0x2)
137
Pratik Patel3b0ca882012-06-01 16:54:14 -0700138enum etm_addr_type {
Pratik Patel6630ebe2012-03-06 16:44:22 -0800139 ETM_ADDR_TYPE_NONE,
140 ETM_ADDR_TYPE_SINGLE,
141 ETM_ADDR_TYPE_RANGE,
142 ETM_ADDR_TYPE_START,
143 ETM_ADDR_TYPE_STOP,
144};
145
Pratik Patel6630ebe2012-03-06 16:44:22 -0800146
Pratik Patel29cba152012-01-03 11:40:26 -0800147#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
Pratik Patel3b0ca882012-06-01 16:54:14 -0700148static int boot_enable = 1;
Pratik Patel29cba152012-01-03 11:40:26 -0800149#else
Pratik Patel3b0ca882012-06-01 16:54:14 -0700150static int boot_enable;
Pratik Patel29cba152012-01-03 11:40:26 -0800151#endif
Pratik Patel7831c082011-06-08 21:44:37 -0700152module_param_named(
Pratik Patel3b0ca882012-06-01 16:54:14 -0700153 boot_enable, boot_enable, int, S_IRUGO
Pratik Patel7831c082011-06-08 21:44:37 -0700154);
155
Pratik Patel16aefdb2012-05-30 10:41:23 -0700156struct etm_drvdata {
Pratik Patel7831c082011-06-08 21:44:37 -0700157 void __iomem *base;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700158 struct device *dev;
159 struct coresight_device *csdev;
160 struct clk *clk;
161 struct mutex mutex;
Pratik Patel7831c082011-06-08 21:44:37 -0700162 struct wake_lock wake_lock;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700163 struct pm_qos_request qos_req;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700164 int cpu;
Pratik Patel61de7302012-03-07 12:06:10 -0800165 uint8_t arch;
166 uint8_t nr_addr_cmp;
167 uint8_t nr_cntr;
168 uint8_t nr_ext_inp;
169 uint8_t nr_ext_out;
170 uint8_t nr_ctxid_cmp;
Pratik Pateld30deda2012-02-01 14:40:55 -0800171 uint8_t reset;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800172 uint32_t mode;
Pratik Patel61de7302012-03-07 12:06:10 -0800173 uint32_t ctrl;
174 uint32_t trigger_event;
175 uint32_t startstop_ctrl;
176 uint32_t enable_event;
177 uint32_t enable_ctrl1;
178 uint32_t fifofull_level;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800179 uint8_t addr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800180 uint32_t addr_val[ETM_MAX_ADDR_CMP];
181 uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
Pratik Patel6630ebe2012-03-06 16:44:22 -0800182 uint32_t addr_type[ETM_MAX_ADDR_CMP];
183 uint8_t cntr_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800184 uint32_t cntr_rld_val[ETM_MAX_CNTR];
185 uint32_t cntr_event[ETM_MAX_CNTR];
186 uint32_t cntr_rld_event[ETM_MAX_CNTR];
187 uint32_t cntr_val[ETM_MAX_CNTR];
188 uint32_t seq_12_event;
189 uint32_t seq_21_event;
190 uint32_t seq_23_event;
191 uint32_t seq_31_event;
192 uint32_t seq_32_event;
193 uint32_t seq_13_event;
194 uint32_t seq_curr_state;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800195 uint8_t ctxid_idx;
Pratik Patel61de7302012-03-07 12:06:10 -0800196 uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
197 uint32_t ctxid_mask;
198 uint32_t sync_freq;
199 uint32_t timestamp_event;
Pratik Patel7831c082011-06-08 21:44:37 -0700200};
201
Pratik Patel7831c082011-06-08 21:44:37 -0700202
Pratik Patel17f3b822011-11-21 12:41:47 -0800203/* ETM clock is derived from the processor clock and gets enabled on a
204 * logical OR of below items on Krait (pass2 onwards):
205 * 1.CPMR[ETMCLKEN] is 1
206 * 2.ETMCR[PD] is 0
207 * 3.ETMPDCR[PU] is 1
208 * 4.Reset is asserted (core or debug)
209 * 5.APB memory mapped requests (eg. EDAP access)
210 *
211 * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
212 * enables
213 *
214 * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
215 * clock vote in the driver and the save-restore code uses 1. above
216 * for its vote
217 */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700218static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700219{
220 uint32_t etmcr;
221
Pratik Patel3b0ca882012-06-01 16:54:14 -0700222 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700223 etmcr |= BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700224 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700225}
226
Pratik Patel3b0ca882012-06-01 16:54:14 -0700227static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700228{
229 uint32_t etmcr;
230
Pratik Patel3b0ca882012-06-01 16:54:14 -0700231 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700232 etmcr &= ~BIT(0);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700233 etm_writel(drvdata, etmcr, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700234}
235
Pratik Patel3b0ca882012-06-01 16:54:14 -0700236static void etm_set_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700237{
238 uint32_t etmcr;
239 int count;
240
Pratik Patel3b0ca882012-06-01 16:54:14 -0700241 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700242 etmcr |= BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700243 etm_writel(drvdata, etmcr, ETMCR);
244 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
Pratik Patel7831c082011-06-08 21:44:37 -0700245 && count > 0; count--)
246 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800247 WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700248 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700249}
250
Pratik Patel3b0ca882012-06-01 16:54:14 -0700251static void etm_clr_prog(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700252{
253 uint32_t etmcr;
254 int count;
255
Pratik Patel3b0ca882012-06-01 16:54:14 -0700256 etmcr = etm_readl(drvdata, ETMCR);
Pratik Patel7831c082011-06-08 21:44:37 -0700257 etmcr &= ~BIT(10);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700258 etm_writel(drvdata, etmcr, ETMCR);
259 for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
Pratik Patel7831c082011-06-08 21:44:37 -0700260 && count > 0; count--)
261 udelay(1);
Pratik Patel61de7302012-03-07 12:06:10 -0800262 WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
Pratik Patel3b0ca882012-06-01 16:54:14 -0700263 etm_readl(drvdata, ETMSR));
Pratik Patel7831c082011-06-08 21:44:37 -0700264}
265
Pratik Patel3b0ca882012-06-01 16:54:14 -0700266static void __etm_enable(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700267{
Pratik Patel17f3b822011-11-21 12:41:47 -0800268 int i;
Pratik Patel7831c082011-06-08 21:44:37 -0700269
Pratik Patel3b0ca882012-06-01 16:54:14 -0700270 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -0800271 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700272 etm_clr_pwrdwn(drvdata);
273 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700274
Pratik Patel3b0ca882012-06-01 16:54:14 -0700275 etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
276 etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
277 etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
278 etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
279 etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
280 etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700281 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700282 etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
283 etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
Pratik Patel7831c082011-06-08 21:44:37 -0700284 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700285 for (i = 0; i < drvdata->nr_cntr; i++) {
Pratik Patel3b0ca882012-06-01 16:54:14 -0700286 etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
287 etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
288 etm_writel(drvdata, drvdata->cntr_rld_event[i],
Pratik Patel16aefdb2012-05-30 10:41:23 -0700289 ETMCNTRLDEVRn(i));
Pratik Patel3b0ca882012-06-01 16:54:14 -0700290 etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
Pratik Patel17f3b822011-11-21 12:41:47 -0800291 }
Pratik Patel3b0ca882012-06-01 16:54:14 -0700292 etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
293 etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
294 etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
295 etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
296 etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
297 etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
298 etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700299 for (i = 0; i < drvdata->nr_ext_out; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700300 etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
Pratik Patel16aefdb2012-05-30 10:41:23 -0700301 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
Pratik Patel3b0ca882012-06-01 16:54:14 -0700302 etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
303 etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
304 etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
305 etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
306 etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
307 etm_writel(drvdata, 0x00000000, ETMAUXCR);
308 etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
309 etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
Pratik Patel17f3b822011-11-21 12:41:47 -0800310
Pratik Patel3b0ca882012-06-01 16:54:14 -0700311 etm_clr_prog(drvdata);
312 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700313}
314
Pratik Patel3b0ca882012-06-01 16:54:14 -0700315static int etm_enable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700316{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700317 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
318 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -0800319
Pratik Patel16aefdb2012-05-30 10:41:23 -0700320 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700321 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700322 * 2. prevents idle PC until save restore flag is enabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700323 *
324 * we rely on the user to prevent hotplug on/off racing with this
325 * operation and to ensure cores where trace is expected to be turned
326 * on are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700327 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700328 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700329
Pratik Patel16aefdb2012-05-30 10:41:23 -0700330 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -0700331 if (ret)
332 goto err_clk;
333
Pratik Patel3b0ca882012-06-01 16:54:14 -0700334 mutex_lock(&drvdata->mutex);
335 __etm_enable(drvdata);
336 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700337
Pratik Patel16aefdb2012-05-30 10:41:23 -0700338 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
339 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700340
Pratik Patel16aefdb2012-05-30 10:41:23 -0700341 dev_info(drvdata->dev, "ETM tracing enabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700342 return 0;
Pratik Patelf17b1472012-05-25 22:23:52 -0700343err_clk:
Pratik Patel16aefdb2012-05-30 10:41:23 -0700344 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
345 wake_unlock(&drvdata->wake_lock);
Pratik Patel61de7302012-03-07 12:06:10 -0800346 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -0700347}
348
Pratik Patel3b0ca882012-06-01 16:54:14 -0700349static void __etm_disable(struct etm_drvdata *drvdata)
Pratik Patel7831c082011-06-08 21:44:37 -0700350{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700351 ETM_UNLOCK(drvdata);
352 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700353
Pratik Patel17f3b822011-11-21 12:41:47 -0800354 /* program trace enable to low by using always false event */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700355 etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
Pratik Patel7831c082011-06-08 21:44:37 -0700356
Pratik Patel17f3b822011-11-21 12:41:47 -0800357 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -0700358 etm_set_pwrdwn(drvdata);
359 ETM_LOCK(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -0700360}
361
Pratik Patel3b0ca882012-06-01 16:54:14 -0700362static void etm_disable(struct coresight_device *csdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700363{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700364 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
Pratik Patel17f3b822011-11-21 12:41:47 -0800365
Pratik Patel16aefdb2012-05-30 10:41:23 -0700366 wake_lock(&drvdata->wake_lock);
Pratik Patele5771792011-09-17 18:33:54 -0700367 /* 1. causes all online cpus to come out of idle PC
Pratik Patel7831c082011-06-08 21:44:37 -0700368 * 2. prevents idle PC until save restore flag is disabled atomically
Pratik Patele5771792011-09-17 18:33:54 -0700369 *
370 * we rely on the user to prevent hotplug on/off racing with this
371 * operation and to ensure cores where trace is expected to be turned
372 * off are already hotplugged on
Pratik Patel7831c082011-06-08 21:44:37 -0700373 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700374 pm_qos_update_request(&drvdata->qos_req, 0);
Pratik Patel7831c082011-06-08 21:44:37 -0700375
Pratik Patel3b0ca882012-06-01 16:54:14 -0700376 mutex_lock(&drvdata->mutex);
377 __etm_disable(drvdata);
378 mutex_unlock(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -0700379
Pratik Patel16aefdb2012-05-30 10:41:23 -0700380 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -0700381
Pratik Patel16aefdb2012-05-30 10:41:23 -0700382 pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
383 wake_unlock(&drvdata->wake_lock);
Pratik Patel7831c082011-06-08 21:44:37 -0700384
Pratik Patel16aefdb2012-05-30 10:41:23 -0700385 dev_info(drvdata->dev, "ETM tracing disabled\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700386}
387
Pratik Patel3b0ca882012-06-01 16:54:14 -0700388static const struct coresight_ops_source etm_source_ops = {
389 .enable = etm_enable,
390 .disable = etm_disable,
391};
Pratik Patel17f3b822011-11-21 12:41:47 -0800392
Pratik Patel3b0ca882012-06-01 16:54:14 -0700393static const struct coresight_ops etm_cs_ops = {
394 .source_ops = &etm_source_ops,
395};
Pratik Patel6630ebe2012-03-06 16:44:22 -0800396
Pratik Patela9c0e062012-05-28 13:45:35 -0700397static ssize_t etm_show_nr_addr_cmp(struct device *dev,
398 struct device_attribute *attr, char *buf)
399{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700400 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700401 unsigned long val = drvdata->nr_addr_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700402
Pratik Patela9c0e062012-05-28 13:45:35 -0700403 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
404}
405static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
406
407static ssize_t etm_show_nr_cntr(struct device *dev,
408 struct device_attribute *attr, char *buf)
409{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700410 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700411 unsigned long val = drvdata->nr_cntr;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700412
Pratik Patela9c0e062012-05-28 13:45:35 -0700413 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
414}
415static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
416
417static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
418 struct device_attribute *attr, char *buf)
419{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700420 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700421 unsigned long val = drvdata->nr_ctxid_cmp;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700422
Pratik Patela9c0e062012-05-28 13:45:35 -0700423 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
424}
425static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
426
427static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
428 char *buf)
429{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700430 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700431 unsigned long val = drvdata->reset;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700432
Pratik Patela9c0e062012-05-28 13:45:35 -0700433 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
434}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800435
Pratik Pateld30deda2012-02-01 14:40:55 -0800436/* Reset to trace everything i.e. exclude nothing. */
Pratik Patela9c0e062012-05-28 13:45:35 -0700437static ssize_t etm_store_reset(struct device *dev,
438 struct device_attribute *attr, const char *buf,
439 size_t size)
Pratik Pateld30deda2012-02-01 14:40:55 -0800440{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700441 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Pateld30deda2012-02-01 14:40:55 -0800442 int i;
443 unsigned long val;
444
445 if (sscanf(buf, "%lx", &val) != 1)
446 return -EINVAL;
447
Pratik Patel16aefdb2012-05-30 10:41:23 -0700448 mutex_lock(&drvdata->mutex);
Pratik Pateld30deda2012-02-01 14:40:55 -0800449 if (val) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700450 drvdata->mode = ETM_MODE_EXCLUDE;
451 drvdata->ctrl = 0x0;
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800452 if (cpu_is_krait_v1()) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700453 drvdata->mode |= ETM_MODE_CYCACC;
454 drvdata->ctrl |= BIT(12);
Pratik Patel2d0c7b62012-02-24 19:04:37 -0800455 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700456 drvdata->trigger_event = 0x406F;
457 drvdata->startstop_ctrl = 0x0;
458 drvdata->enable_event = 0x6F;
459 drvdata->enable_ctrl1 = 0x1000000;
460 drvdata->fifofull_level = 0x28;
461 drvdata->addr_idx = 0x0;
462 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
463 drvdata->addr_val[i] = 0x0;
464 drvdata->addr_acctype[i] = 0x0;
465 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
Pratik Pateld30deda2012-02-01 14:40:55 -0800466 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700467 drvdata->cntr_idx = 0x0;
468 for (i = 0; i < drvdata->nr_cntr; i++) {
469 drvdata->cntr_rld_val[i] = 0x0;
470 drvdata->cntr_event[i] = 0x406F;
471 drvdata->cntr_rld_event[i] = 0x406F;
472 drvdata->cntr_val[i] = 0x0;
Pratik Pateld30deda2012-02-01 14:40:55 -0800473 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700474 drvdata->seq_12_event = 0x406F;
475 drvdata->seq_21_event = 0x406F;
476 drvdata->seq_23_event = 0x406F;
477 drvdata->seq_31_event = 0x406F;
478 drvdata->seq_32_event = 0x406F;
479 drvdata->seq_13_event = 0x406F;
480 drvdata->seq_curr_state = 0x0;
481 drvdata->ctxid_idx = 0x0;
482 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
483 drvdata->ctxid_val[i] = 0x0;
484 drvdata->ctxid_mask = 0x0;
Pratik Patel77b90632012-07-17 17:54:51 -0700485 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
486 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
487 drvdata->sync_freq = 0x100;
488 else
489 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700490 drvdata->timestamp_event = 0x406F;
Pratik Pateld30deda2012-02-01 14:40:55 -0800491 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700492 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700493 return size;
Pratik Pateld30deda2012-02-01 14:40:55 -0800494}
Pratik Patela9c0e062012-05-28 13:45:35 -0700495static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
Pratik Pateld30deda2012-02-01 14:40:55 -0800496
Pratik Patela9c0e062012-05-28 13:45:35 -0700497static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
498 char *buf)
499{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700500 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700501 unsigned long val = drvdata->mode;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700502
Pratik Patela9c0e062012-05-28 13:45:35 -0700503 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
504}
505
506static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
507 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800508{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700509 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800510 unsigned long val;
511
512 if (sscanf(buf, "%lx", &val) != 1)
513 return -EINVAL;
514
Pratik Patel16aefdb2012-05-30 10:41:23 -0700515 mutex_lock(&drvdata->mutex);
516 drvdata->mode = val & ETM_MODE_ALL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800517
Pratik Patel16aefdb2012-05-30 10:41:23 -0700518 if (drvdata->mode & ETM_MODE_EXCLUDE)
519 drvdata->enable_ctrl1 |= BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800520 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700521 drvdata->enable_ctrl1 &= ~BIT(24);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800522
Pratik Patel16aefdb2012-05-30 10:41:23 -0700523 if (drvdata->mode & ETM_MODE_CYCACC)
524 drvdata->ctrl |= BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800525 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700526 drvdata->ctrl &= ~BIT(12);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800527
Pratik Patel16aefdb2012-05-30 10:41:23 -0700528 if (drvdata->mode & ETM_MODE_STALL)
529 drvdata->ctrl |= BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800530 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700531 drvdata->ctrl &= ~BIT(7);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800532
Pratik Patel16aefdb2012-05-30 10:41:23 -0700533 if (drvdata->mode & ETM_MODE_TIMESTAMP)
534 drvdata->ctrl |= BIT(28);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800535 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700536 drvdata->ctrl &= ~BIT(28);
Pratik Patel3b0ca882012-06-01 16:54:14 -0700537
Pratik Patel16aefdb2012-05-30 10:41:23 -0700538 if (drvdata->mode & ETM_MODE_CTXID)
539 drvdata->ctrl |= (BIT(14) | BIT(15));
Pratik Patel6630ebe2012-03-06 16:44:22 -0800540 else
Pratik Patel16aefdb2012-05-30 10:41:23 -0700541 drvdata->ctrl &= ~(BIT(14) | BIT(15));
542 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800543
Pratik Patela9c0e062012-05-28 13:45:35 -0700544 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800545}
Pratik Patela9c0e062012-05-28 13:45:35 -0700546static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800547
Pratik Patela9c0e062012-05-28 13:45:35 -0700548static ssize_t etm_show_trigger_event(struct device *dev,
549 struct device_attribute *attr, char *buf)
550{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700551 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700552 unsigned long val = drvdata->trigger_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700553
Pratik Patela9c0e062012-05-28 13:45:35 -0700554 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
555}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800556
Pratik Patela9c0e062012-05-28 13:45:35 -0700557static ssize_t etm_store_trigger_event(struct device *dev,
558 struct device_attribute *attr,
559 const char *buf, size_t size)
560{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700561 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700562 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800563
Pratik Patela9c0e062012-05-28 13:45:35 -0700564 if (sscanf(buf, "%lx", &val) != 1)
565 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800566
Pratik Patel16aefdb2012-05-30 10:41:23 -0700567 drvdata->trigger_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700568 return size;
569}
570static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
571 etm_store_trigger_event);
572
573static ssize_t etm_show_enable_event(struct device *dev,
574 struct device_attribute *attr, char *buf)
575{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700576 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700577 unsigned long val = drvdata->enable_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700578
Pratik Patela9c0e062012-05-28 13:45:35 -0700579 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
580}
581
582static ssize_t etm_store_enable_event(struct device *dev,
583 struct device_attribute *attr,
584 const char *buf, size_t size)
585{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700586 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700587 unsigned long val;
588
589 if (sscanf(buf, "%lx", &val) != 1)
590 return -EINVAL;
591
Pratik Patel16aefdb2012-05-30 10:41:23 -0700592 drvdata->enable_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -0700593 return size;
594}
595static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
596 etm_store_enable_event);
597
598static ssize_t etm_show_fifofull_level(struct device *dev,
599 struct device_attribute *attr, char *buf)
600{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700601 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700602 unsigned long val = drvdata->fifofull_level;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700603
Pratik Patela9c0e062012-05-28 13:45:35 -0700604 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
605}
606
607static ssize_t etm_store_fifofull_level(struct device *dev,
608 struct device_attribute *attr,
609 const char *buf, size_t size)
610{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700611 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700612 unsigned long val;
613
614 if (sscanf(buf, "%lx", &val) != 1)
615 return -EINVAL;
616
Pratik Patel16aefdb2012-05-30 10:41:23 -0700617 drvdata->fifofull_level = val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700618 return size;
619}
620static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
621 etm_store_fifofull_level);
622
623static ssize_t etm_show_addr_idx(struct device *dev,
624 struct device_attribute *attr, char *buf)
625{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700626 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700627 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700628
Pratik Patela9c0e062012-05-28 13:45:35 -0700629 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
630}
631
632static ssize_t etm_store_addr_idx(struct device *dev,
633 struct device_attribute *attr,
634 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800635{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700636 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800637 unsigned long val;
638
639 if (sscanf(buf, "%lx", &val) != 1)
640 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700641 if (val >= drvdata->nr_addr_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800642 return -EINVAL;
643
644 /* Use mutex to ensure index doesn't change while it gets dereferenced
645 * multiple times within a mutex block elsewhere.
646 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700647 mutex_lock(&drvdata->mutex);
648 drvdata->addr_idx = val;
649 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700650 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800651}
Pratik Patela9c0e062012-05-28 13:45:35 -0700652static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
653 etm_store_addr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800654
Pratik Patela9c0e062012-05-28 13:45:35 -0700655static ssize_t etm_show_addr_single(struct device *dev,
656 struct device_attribute *attr, char *buf)
657{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700658 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700659 unsigned long val;
660 uint8_t idx;
661
Pratik Patel16aefdb2012-05-30 10:41:23 -0700662 mutex_lock(&drvdata->mutex);
663 idx = drvdata->addr_idx;
664 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
665 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
666 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700667 return -EPERM;
668 }
669
Pratik Patel16aefdb2012-05-30 10:41:23 -0700670 val = drvdata->addr_val[idx];
671 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700672 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
673}
674
675static ssize_t etm_store_addr_single(struct device *dev,
676 struct device_attribute *attr,
677 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800678{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700679 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800680 unsigned long val;
681 uint8_t idx;
682
683 if (sscanf(buf, "%lx", &val) != 1)
684 return -EINVAL;
685
Pratik Patel16aefdb2012-05-30 10:41:23 -0700686 mutex_lock(&drvdata->mutex);
687 idx = drvdata->addr_idx;
688 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
689 drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
690 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800691 return -EPERM;
692 }
693
Pratik Patel16aefdb2012-05-30 10:41:23 -0700694 drvdata->addr_val[idx] = val;
695 drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
696 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700697 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800698}
Pratik Patela9c0e062012-05-28 13:45:35 -0700699static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
700 etm_store_addr_single);
701
702static ssize_t etm_show_addr_range(struct device *dev,
703 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800704{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700705 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700706 unsigned long val1, val2;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800707 uint8_t idx;
708
Pratik Patel16aefdb2012-05-30 10:41:23 -0700709 mutex_lock(&drvdata->mutex);
710 idx = drvdata->addr_idx;
Pratik Patela9c0e062012-05-28 13:45:35 -0700711 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700712 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700713 return -EPERM;
714 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700715 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
716 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
717 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
718 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
719 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800720 return -EPERM;
721 }
722
Pratik Patel16aefdb2012-05-30 10:41:23 -0700723 val1 = drvdata->addr_val[idx];
724 val2 = drvdata->addr_val[idx + 1];
725 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700726 return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800727}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800728
Pratik Patela9c0e062012-05-28 13:45:35 -0700729static ssize_t etm_store_addr_range(struct device *dev,
730 struct device_attribute *attr,
731 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800732{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700733 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800734 unsigned long val1, val2;
735 uint8_t idx;
736
737 if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
738 return -EINVAL;
739 /* lower address comparator cannot have a higher address value */
740 if (val1 > val2)
741 return -EINVAL;
742
Pratik Patel16aefdb2012-05-30 10:41:23 -0700743 mutex_lock(&drvdata->mutex);
744 idx = drvdata->addr_idx;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800745 if (idx % 2 != 0) {
Pratik Patel16aefdb2012-05-30 10:41:23 -0700746 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800747 return -EPERM;
748 }
Pratik Patel16aefdb2012-05-30 10:41:23 -0700749 if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
750 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
751 (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
752 drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
753 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800754 return -EPERM;
755 }
756
Pratik Patel16aefdb2012-05-30 10:41:23 -0700757 drvdata->addr_val[idx] = val1;
758 drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
759 drvdata->addr_val[idx + 1] = val2;
760 drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
761 drvdata->enable_ctrl1 |= (1 << (idx/2));
762 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700763 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800764}
Pratik Patela9c0e062012-05-28 13:45:35 -0700765static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
766 etm_store_addr_range);
767
768static ssize_t etm_show_addr_start(struct device *dev,
769 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800770{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700771 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700772 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800773 uint8_t idx;
774
Pratik Patel16aefdb2012-05-30 10:41:23 -0700775 mutex_lock(&drvdata->mutex);
776 idx = drvdata->addr_idx;
777 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
778 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
779 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800780 return -EPERM;
781 }
782
Pratik Patel16aefdb2012-05-30 10:41:23 -0700783 val = drvdata->addr_val[idx];
784 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700785 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800786}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800787
Pratik Patela9c0e062012-05-28 13:45:35 -0700788static ssize_t etm_store_addr_start(struct device *dev,
789 struct device_attribute *attr,
790 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800791{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700792 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800793 unsigned long val;
794 uint8_t idx;
795
796 if (sscanf(buf, "%lx", &val) != 1)
797 return -EINVAL;
798
Pratik Patel16aefdb2012-05-30 10:41:23 -0700799 mutex_lock(&drvdata->mutex);
800 idx = drvdata->addr_idx;
801 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
802 drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
803 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800804 return -EPERM;
805 }
806
Pratik Patel16aefdb2012-05-30 10:41:23 -0700807 drvdata->addr_val[idx] = val;
808 drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
809 drvdata->startstop_ctrl |= (1 << idx);
810 drvdata->enable_ctrl1 |= BIT(25);
811 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700812 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800813}
Pratik Patela9c0e062012-05-28 13:45:35 -0700814static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
815 etm_store_addr_start);
816
817static ssize_t etm_show_addr_stop(struct device *dev,
818 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800819{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700820 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800821 unsigned long val;
822 uint8_t idx;
823
Pratik Patel16aefdb2012-05-30 10:41:23 -0700824 mutex_lock(&drvdata->mutex);
825 idx = drvdata->addr_idx;
826 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
827 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
828 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800829 return -EPERM;
830 }
831
Pratik Patel16aefdb2012-05-30 10:41:23 -0700832 val = drvdata->addr_val[idx];
833 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800834 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
835}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800836
Pratik Patela9c0e062012-05-28 13:45:35 -0700837static ssize_t etm_store_addr_stop(struct device *dev,
838 struct device_attribute *attr,
839 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800840{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700841 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800842 unsigned long val;
843 uint8_t idx;
844
845 if (sscanf(buf, "%lx", &val) != 1)
846 return -EINVAL;
847
Pratik Patel16aefdb2012-05-30 10:41:23 -0700848 mutex_lock(&drvdata->mutex);
849 idx = drvdata->addr_idx;
850 if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
851 drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
852 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800853 return -EPERM;
854 }
855
Pratik Patel16aefdb2012-05-30 10:41:23 -0700856 drvdata->addr_val[idx] = val;
857 drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
858 drvdata->startstop_ctrl |= (1 << (idx + 16));
859 drvdata->enable_ctrl1 |= BIT(25);
860 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700861 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800862}
Pratik Patela9c0e062012-05-28 13:45:35 -0700863static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
864 etm_store_addr_stop);
865
866static ssize_t etm_show_addr_acctype(struct device *dev,
867 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800868{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700869 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800870 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800871
Pratik Patel16aefdb2012-05-30 10:41:23 -0700872 mutex_lock(&drvdata->mutex);
873 val = drvdata->addr_acctype[drvdata->addr_idx];
874 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800875 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
876}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800877
Pratik Patela9c0e062012-05-28 13:45:35 -0700878static ssize_t etm_store_addr_acctype(struct device *dev,
879 struct device_attribute *attr,
880 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800881{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700882 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800883 unsigned long val;
884
885 if (sscanf(buf, "%lx", &val) != 1)
886 return -EINVAL;
887
Pratik Patel16aefdb2012-05-30 10:41:23 -0700888 mutex_lock(&drvdata->mutex);
889 drvdata->addr_acctype[drvdata->addr_idx] = val;
890 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700891 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800892}
Pratik Patela9c0e062012-05-28 13:45:35 -0700893static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
894 etm_store_addr_acctype);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800895
Pratik Patela9c0e062012-05-28 13:45:35 -0700896static ssize_t etm_show_cntr_idx(struct device *dev,
897 struct device_attribute *attr, char *buf)
898{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700899 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -0700900 unsigned long val = drvdata->addr_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700901
Pratik Patel6630ebe2012-03-06 16:44:22 -0800902 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
903}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800904
Pratik Patela9c0e062012-05-28 13:45:35 -0700905static ssize_t etm_store_cntr_idx(struct device *dev,
906 struct device_attribute *attr,
907 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800908{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700909 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800910 unsigned long val;
911
912 if (sscanf(buf, "%lx", &val) != 1)
913 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -0700914 if (val >= drvdata->nr_cntr)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800915 return -EINVAL;
916
917 /* Use mutex to ensure index doesn't change while it gets dereferenced
918 * multiple times within a mutex block elsewhere.
919 */
Pratik Patel16aefdb2012-05-30 10:41:23 -0700920 mutex_lock(&drvdata->mutex);
921 drvdata->cntr_idx = val;
922 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700923 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800924}
Pratik Patela9c0e062012-05-28 13:45:35 -0700925static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
926 etm_store_cntr_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800927
Pratik Patela9c0e062012-05-28 13:45:35 -0700928static ssize_t etm_show_cntr_rld_val(struct device *dev,
929 struct device_attribute *attr, char *buf)
930{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700931 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -0700932 unsigned long val;
Pratik Patel3b0ca882012-06-01 16:54:14 -0700933
Pratik Patel16aefdb2012-05-30 10:41:23 -0700934 mutex_lock(&drvdata->mutex);
935 val = drvdata->cntr_rld_val[drvdata->cntr_idx];
936 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700937 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
938}
939
940static ssize_t etm_store_cntr_rld_val(struct device *dev,
941 struct device_attribute *attr,
942 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800943{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700944 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800945 unsigned long val;
946
947 if (sscanf(buf, "%lx", &val) != 1)
948 return -EINVAL;
949
Pratik Patel16aefdb2012-05-30 10:41:23 -0700950 mutex_lock(&drvdata->mutex);
951 drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
952 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700953 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800954}
Pratik Patela9c0e062012-05-28 13:45:35 -0700955static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
956 etm_store_cntr_rld_val);
957
958static ssize_t etm_show_cntr_event(struct device *dev,
959 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800960{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700961 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800962 unsigned long val;
Pratik Patela9c0e062012-05-28 13:45:35 -0700963
Pratik Patel16aefdb2012-05-30 10:41:23 -0700964 mutex_lock(&drvdata->mutex);
965 val = drvdata->cntr_event[drvdata->cntr_idx];
966 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800967 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
968}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800969
Pratik Patela9c0e062012-05-28 13:45:35 -0700970static ssize_t etm_store_cntr_event(struct device *dev,
971 struct device_attribute *attr,
972 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800973{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700974 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800975 unsigned long val;
976
977 if (sscanf(buf, "%lx", &val) != 1)
978 return -EINVAL;
979
Pratik Patel16aefdb2012-05-30 10:41:23 -0700980 mutex_lock(&drvdata->mutex);
981 drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
982 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -0700983 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800984}
Pratik Patela9c0e062012-05-28 13:45:35 -0700985static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
986 etm_store_cntr_event);
987
988static ssize_t etm_show_cntr_rld_event(struct device *dev,
989 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800990{
Pratik Patel3b0ca882012-06-01 16:54:14 -0700991 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800992 unsigned long val;
993
Pratik Patel16aefdb2012-05-30 10:41:23 -0700994 mutex_lock(&drvdata->mutex);
995 val = drvdata->cntr_rld_event[drvdata->cntr_idx];
996 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -0800997 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
998}
Pratik Patel6630ebe2012-03-06 16:44:22 -0800999
Pratik Patela9c0e062012-05-28 13:45:35 -07001000static ssize_t etm_store_cntr_rld_event(struct device *dev,
1001 struct device_attribute *attr,
1002 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001003{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001004 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001005 unsigned long val;
1006
1007 if (sscanf(buf, "%lx", &val) != 1)
1008 return -EINVAL;
1009
Pratik Patel16aefdb2012-05-30 10:41:23 -07001010 mutex_lock(&drvdata->mutex);
1011 drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
1012 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001013 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001014}
Pratik Patela9c0e062012-05-28 13:45:35 -07001015static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
1016 etm_store_cntr_rld_event);
1017
1018static ssize_t etm_show_cntr_val(struct device *dev,
1019 struct device_attribute *attr, char *buf)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001020{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001021 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001022 unsigned long val;
1023
Pratik Patel16aefdb2012-05-30 10:41:23 -07001024 mutex_lock(&drvdata->mutex);
1025 val = drvdata->cntr_val[drvdata->cntr_idx];
1026 mutex_unlock(&drvdata->mutex);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001027 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1028}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001029
Pratik Patela9c0e062012-05-28 13:45:35 -07001030static ssize_t etm_store_cntr_val(struct device *dev,
1031 struct device_attribute *attr,
1032 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001033{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001034 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001035 unsigned long val;
1036
1037 if (sscanf(buf, "%lx", &val) != 1)
1038 return -EINVAL;
1039
Pratik Patel16aefdb2012-05-30 10:41:23 -07001040 mutex_lock(&drvdata->mutex);
1041 drvdata->cntr_val[drvdata->cntr_idx] = val;
1042 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001043 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001044}
Pratik Patela9c0e062012-05-28 13:45:35 -07001045static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
1046 etm_store_cntr_val);
1047
1048static ssize_t etm_show_seq_12_event(struct device *dev,
1049 struct device_attribute *attr, char *buf)
1050{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001051 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001052 unsigned long val = drvdata->seq_12_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001053
Pratik Patela9c0e062012-05-28 13:45:35 -07001054 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1055}
1056
1057static ssize_t etm_store_seq_12_event(struct device *dev,
1058 struct device_attribute *attr,
1059 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001060{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001061 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001062 unsigned long val;
1063
Pratik Patela9c0e062012-05-28 13:45:35 -07001064 if (sscanf(buf, "%lx", &val) != 1)
1065 return -EINVAL;
1066
Pratik Patel16aefdb2012-05-30 10:41:23 -07001067 drvdata->seq_12_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001068 return size;
1069}
1070static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
1071 etm_store_seq_12_event);
1072
1073static ssize_t etm_show_seq_21_event(struct device *dev,
1074 struct device_attribute *attr, char *buf)
1075{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001076 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001077 unsigned long val = drvdata->seq_21_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001078
Pratik Patel6630ebe2012-03-06 16:44:22 -08001079 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1080}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001081
Pratik Patela9c0e062012-05-28 13:45:35 -07001082static ssize_t etm_store_seq_21_event(struct device *dev,
1083 struct device_attribute *attr,
1084 const char *buf, size_t size)
1085{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001086 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001087 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001088
Pratik Patela9c0e062012-05-28 13:45:35 -07001089 if (sscanf(buf, "%lx", &val) != 1)
1090 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001091
Pratik Patel16aefdb2012-05-30 10:41:23 -07001092 drvdata->seq_21_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001093 return size;
1094}
1095static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
1096 etm_store_seq_21_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001097
Pratik Patela9c0e062012-05-28 13:45:35 -07001098static ssize_t etm_show_seq_23_event(struct device *dev,
1099 struct device_attribute *attr, char *buf)
1100{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001101 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001102 unsigned long val = drvdata->seq_23_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001103
Pratik Patela9c0e062012-05-28 13:45:35 -07001104 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1105}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001106
Pratik Patela9c0e062012-05-28 13:45:35 -07001107static ssize_t etm_store_seq_23_event(struct device *dev,
1108 struct device_attribute *attr,
1109 const char *buf, size_t size)
1110{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001111 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001112 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001113
Pratik Patela9c0e062012-05-28 13:45:35 -07001114 if (sscanf(buf, "%lx", &val) != 1)
1115 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001116
Pratik Patel16aefdb2012-05-30 10:41:23 -07001117 drvdata->seq_23_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001118 return size;
1119}
1120static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
1121 etm_store_seq_23_event);
1122
1123static ssize_t etm_show_seq_31_event(struct device *dev,
1124 struct device_attribute *attr, char *buf)
1125{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001126 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001127 unsigned long val = drvdata->seq_31_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001128
Pratik Patela9c0e062012-05-28 13:45:35 -07001129 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1130}
1131
1132static ssize_t etm_store_seq_31_event(struct device *dev,
1133 struct device_attribute *attr,
1134 const char *buf, size_t size)
1135{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001136 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001137 unsigned long val;
1138
1139 if (sscanf(buf, "%lx", &val) != 1)
1140 return -EINVAL;
1141
Pratik Patel16aefdb2012-05-30 10:41:23 -07001142 drvdata->seq_31_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001143 return size;
1144}
1145static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
1146 etm_store_seq_31_event);
1147
1148static ssize_t etm_show_seq_32_event(struct device *dev,
1149 struct device_attribute *attr, char *buf)
1150{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001151 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001152 unsigned long val = drvdata->seq_32_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001153
Pratik Patela9c0e062012-05-28 13:45:35 -07001154 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1155}
1156
1157static ssize_t etm_store_seq_32_event(struct device *dev,
1158 struct device_attribute *attr,
1159 const char *buf, size_t size)
1160{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001161 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001162 unsigned long val;
1163
1164 if (sscanf(buf, "%lx", &val) != 1)
1165 return -EINVAL;
1166
Pratik Patel16aefdb2012-05-30 10:41:23 -07001167 drvdata->seq_32_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001168 return size;
1169}
1170static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
1171 etm_store_seq_32_event);
1172
1173static ssize_t etm_show_seq_13_event(struct device *dev,
1174 struct device_attribute *attr, char *buf)
1175{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001176 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001177 unsigned long val = drvdata->seq_13_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001178
Pratik Patela9c0e062012-05-28 13:45:35 -07001179 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1180}
1181
1182static ssize_t etm_store_seq_13_event(struct device *dev,
1183 struct device_attribute *attr,
1184 const char *buf, size_t size)
1185{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001186 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001187 unsigned long val;
1188
1189 if (sscanf(buf, "%lx", &val) != 1)
1190 return -EINVAL;
1191
Pratik Patel16aefdb2012-05-30 10:41:23 -07001192 drvdata->seq_13_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001193 return size;
1194}
1195static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
1196 etm_store_seq_13_event);
1197
1198static ssize_t etm_show_seq_curr_state(struct device *dev,
1199 struct device_attribute *attr, char *buf)
1200{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001201 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001202 unsigned long val = drvdata->seq_curr_state;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001203
Pratik Patela9c0e062012-05-28 13:45:35 -07001204 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1205}
1206
1207static ssize_t etm_store_seq_curr_state(struct device *dev,
1208 struct device_attribute *attr,
1209 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001210{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001211 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001212 unsigned long val;
1213
1214 if (sscanf(buf, "%lx", &val) != 1)
1215 return -EINVAL;
1216 if (val > ETM_SEQ_STATE_MAX_VAL)
1217 return -EINVAL;
1218
Pratik Patel16aefdb2012-05-30 10:41:23 -07001219 drvdata->seq_curr_state = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001220 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001221}
Pratik Patela9c0e062012-05-28 13:45:35 -07001222static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
1223 etm_store_seq_curr_state);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001224
Pratik Patela9c0e062012-05-28 13:45:35 -07001225static ssize_t etm_show_ctxid_idx(struct device *dev,
1226 struct device_attribute *attr, char *buf)
1227{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001228 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001229 unsigned long val = drvdata->ctxid_idx;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001230
Pratik Patela9c0e062012-05-28 13:45:35 -07001231 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1232}
1233
1234static ssize_t etm_store_ctxid_idx(struct device *dev,
1235 struct device_attribute *attr,
1236 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001237{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001238 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001239 unsigned long val;
1240
1241 if (sscanf(buf, "%lx", &val) != 1)
1242 return -EINVAL;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001243 if (val >= drvdata->nr_ctxid_cmp)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001244 return -EINVAL;
1245
1246 /* Use mutex to ensure index doesn't change while it gets dereferenced
1247 * multiple times within a mutex block elsewhere.
1248 */
Pratik Patel16aefdb2012-05-30 10:41:23 -07001249 mutex_lock(&drvdata->mutex);
1250 drvdata->ctxid_idx = val;
1251 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001252 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001253}
Pratik Patela9c0e062012-05-28 13:45:35 -07001254static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
1255 etm_store_ctxid_idx);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001256
Pratik Patela9c0e062012-05-28 13:45:35 -07001257static ssize_t etm_show_ctxid_val(struct device *dev,
1258 struct device_attribute *attr, char *buf)
1259{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001260 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001261 unsigned long val;
1262
Pratik Patel16aefdb2012-05-30 10:41:23 -07001263 mutex_lock(&drvdata->mutex);
1264 val = drvdata->ctxid_val[drvdata->ctxid_idx];
1265 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001266 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1267}
1268
1269static ssize_t etm_store_ctxid_val(struct device *dev,
1270 struct device_attribute *attr,
1271 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001272{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001273 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001274 unsigned long val;
1275
1276 if (sscanf(buf, "%lx", &val) != 1)
1277 return -EINVAL;
1278
Pratik Patel16aefdb2012-05-30 10:41:23 -07001279 mutex_lock(&drvdata->mutex);
1280 drvdata->ctxid_val[drvdata->ctxid_idx] = val;
1281 mutex_unlock(&drvdata->mutex);
Pratik Patela9c0e062012-05-28 13:45:35 -07001282 return size;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001283}
Pratik Patela9c0e062012-05-28 13:45:35 -07001284static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
1285 etm_store_ctxid_val);
1286
1287static ssize_t etm_show_ctxid_mask(struct device *dev,
1288 struct device_attribute *attr, char *buf)
1289{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001290 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001291 unsigned long val = drvdata->ctxid_mask;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001292
Pratik Patela9c0e062012-05-28 13:45:35 -07001293 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1294}
1295
1296static ssize_t etm_store_ctxid_mask(struct device *dev,
1297 struct device_attribute *attr,
1298 const char *buf, size_t size)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001299{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001300 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001301 unsigned long val;
1302
Pratik Patela9c0e062012-05-28 13:45:35 -07001303 if (sscanf(buf, "%lx", &val) != 1)
1304 return -EINVAL;
1305
Pratik Patel16aefdb2012-05-30 10:41:23 -07001306 drvdata->ctxid_mask = val;
Pratik Patela9c0e062012-05-28 13:45:35 -07001307 return size;
1308}
1309static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
1310 etm_store_ctxid_mask);
1311
1312static ssize_t etm_show_sync_freq(struct device *dev,
1313 struct device_attribute *attr, char *buf)
1314{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001315 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001316 unsigned long val = drvdata->sync_freq;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001317 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1318}
Pratik Patel6630ebe2012-03-06 16:44:22 -08001319
Pratik Patela9c0e062012-05-28 13:45:35 -07001320static ssize_t etm_store_sync_freq(struct device *dev,
1321 struct device_attribute *attr,
1322 const char *buf, size_t size)
1323{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001324 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001325 unsigned long val;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001326
Pratik Patela9c0e062012-05-28 13:45:35 -07001327 if (sscanf(buf, "%lx", &val) != 1)
1328 return -EINVAL;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001329
Pratik Patel16aefdb2012-05-30 10:41:23 -07001330 drvdata->sync_freq = val & ETM_SYNC_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001331 return size;
1332}
1333static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
1334 etm_store_sync_freq);
1335
1336static ssize_t etm_show_timestamp_event(struct device *dev,
1337 struct device_attribute *attr,
1338 char *buf)
1339{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001340 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001341 unsigned long val = drvdata->timestamp_event;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001342
Pratik Patela9c0e062012-05-28 13:45:35 -07001343 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1344}
1345
1346static ssize_t etm_store_timestamp_event(struct device *dev,
1347 struct device_attribute *attr,
1348 const char *buf, size_t size)
1349{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001350 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Pratik Patela9c0e062012-05-28 13:45:35 -07001351 unsigned long val;
1352
1353 if (sscanf(buf, "%lx", &val) != 1)
1354 return -EINVAL;
1355
Pratik Patel16aefdb2012-05-30 10:41:23 -07001356 drvdata->timestamp_event = val & ETM_EVENT_MASK;
Pratik Patela9c0e062012-05-28 13:45:35 -07001357 return size;
1358}
1359static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
1360 etm_store_timestamp_event);
Pratik Patel6630ebe2012-03-06 16:44:22 -08001361
1362static struct attribute *etm_attrs[] = {
Pratik Patela9c0e062012-05-28 13:45:35 -07001363 &dev_attr_nr_addr_cmp.attr,
1364 &dev_attr_nr_cntr.attr,
1365 &dev_attr_nr_ctxid_cmp.attr,
1366 &dev_attr_reset.attr,
1367 &dev_attr_mode.attr,
1368 &dev_attr_trigger_event.attr,
1369 &dev_attr_enable_event.attr,
1370 &dev_attr_fifofull_level.attr,
1371 &dev_attr_addr_idx.attr,
1372 &dev_attr_addr_single.attr,
1373 &dev_attr_addr_range.attr,
1374 &dev_attr_addr_start.attr,
1375 &dev_attr_addr_stop.attr,
1376 &dev_attr_addr_acctype.attr,
1377 &dev_attr_cntr_idx.attr,
1378 &dev_attr_cntr_rld_val.attr,
1379 &dev_attr_cntr_event.attr,
1380 &dev_attr_cntr_rld_event.attr,
1381 &dev_attr_cntr_val.attr,
1382 &dev_attr_seq_12_event.attr,
1383 &dev_attr_seq_21_event.attr,
1384 &dev_attr_seq_23_event.attr,
1385 &dev_attr_seq_31_event.attr,
1386 &dev_attr_seq_32_event.attr,
1387 &dev_attr_seq_13_event.attr,
1388 &dev_attr_seq_curr_state.attr,
1389 &dev_attr_ctxid_idx.attr,
1390 &dev_attr_ctxid_val.attr,
1391 &dev_attr_ctxid_mask.attr,
1392 &dev_attr_sync_freq.attr,
1393 &dev_attr_timestamp_event.attr,
Pratik Patel6630ebe2012-03-06 16:44:22 -08001394 NULL,
1395};
1396
1397static struct attribute_group etm_attr_grp = {
1398 .attrs = etm_attrs,
1399};
1400
Pratik Patel3b0ca882012-06-01 16:54:14 -07001401static const struct attribute_group *etm_attr_grps[] = {
1402 &etm_attr_grp,
1403 NULL,
1404};
1405
1406/* Memory mapped writes to clear os lock not supported */
1407static void etm_os_unlock(void *unused)
Pratik Patel6630ebe2012-03-06 16:44:22 -08001408{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001409 unsigned long value = 0x0;
Pratik Patel6630ebe2012-03-06 16:44:22 -08001410
Pratik Patel3b0ca882012-06-01 16:54:14 -07001411 asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
1412 asm("isb\n\t");
Pratik Patel6630ebe2012-03-06 16:44:22 -08001413}
1414
Stephen Boyda9510502012-04-24 16:23:34 -07001415static bool __devinit etm_arch_supported(uint8_t arch)
Pratik Patel7831c082011-06-08 21:44:37 -07001416{
Pratik Patel61de7302012-03-07 12:06:10 -08001417 switch (arch) {
1418 case PFT_ARCH_V1_1:
1419 break;
1420 default:
1421 return false;
1422 }
1423 return true;
1424}
1425
Pratik Patel3b0ca882012-06-01 16:54:14 -07001426static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
Pratik Patel61de7302012-03-07 12:06:10 -08001427{
Pratik Patel16aefdb2012-05-30 10:41:23 -07001428 int ret;
Pratik Patel61de7302012-03-07 12:06:10 -08001429 uint32_t etmidr;
1430 uint32_t etmccr;
Pratik Patel7831c082011-06-08 21:44:37 -07001431
Pratik Patel17f3b822011-11-21 12:41:47 -08001432 /* Unlock OS lock first to allow memory mapped reads and writes */
Pratik Patel492b3012012-03-06 14:22:30 -08001433 etm_os_unlock(NULL);
1434 smp_call_function(etm_os_unlock, NULL, 1);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001435 ETM_UNLOCK(drvdata);
Pratik Patel17f3b822011-11-21 12:41:47 -08001436 /* Vote for ETM power/clock enable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001437 etm_clr_pwrdwn(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001438 /* Set prog bit. It will be set from reset but this is included to
1439 * ensure it is set
1440 */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001441 etm_set_prog(drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001442
1443 /* find all capabilities */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001444 etmidr = etm_readl(drvdata, ETMIDR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001445 drvdata->arch = BMVAL(etmidr, 4, 11);
1446 if (etm_arch_supported(drvdata->arch) == false) {
Pratik Patel61de7302012-03-07 12:06:10 -08001447 ret = -EINVAL;
1448 goto err;
1449 }
Pratik Patel7831c082011-06-08 21:44:37 -07001450
Pratik Patel3b0ca882012-06-01 16:54:14 -07001451 etmccr = etm_readl(drvdata, ETMCCR);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001452 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
1453 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
1454 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
1455 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
1456 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
Pratik Patel2d0c7b62012-02-24 19:04:37 -08001457
Pratik Patel17f3b822011-11-21 12:41:47 -08001458 /* Vote for ETM power/clock disable */
Pratik Patel3b0ca882012-06-01 16:54:14 -07001459 etm_set_pwrdwn(drvdata);
1460 ETM_LOCK(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001461
1462 return 0;
1463err:
1464 return ret;
Pratik Patel7831c082011-06-08 21:44:37 -07001465}
1466
Pratik Patel3b0ca882012-06-01 16:54:14 -07001467static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
Pratik Patel16aefdb2012-05-30 10:41:23 -07001468{
1469 int i;
1470
1471 drvdata->trigger_event = 0x406F;
1472 drvdata->enable_event = 0x6F;
1473 drvdata->enable_ctrl1 = 0x1;
1474 drvdata->fifofull_level = 0x28;
1475 if (drvdata->nr_addr_cmp >= 2) {
1476 drvdata->addr_val[0] = (uint32_t) _stext;
1477 drvdata->addr_val[1] = (uint32_t) _etext;
1478 drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
1479 drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
1480 }
1481 for (i = 0; i < drvdata->nr_cntr; i++) {
1482 drvdata->cntr_event[i] = 0x406F;
1483 drvdata->cntr_rld_event[i] = 0x406F;
1484 }
1485 drvdata->seq_12_event = 0x406F;
1486 drvdata->seq_21_event = 0x406F;
1487 drvdata->seq_23_event = 0x406F;
1488 drvdata->seq_31_event = 0x406F;
1489 drvdata->seq_32_event = 0x406F;
1490 drvdata->seq_13_event = 0x406F;
Pratik Patel77b90632012-07-17 17:54:51 -07001491 /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
1492 if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
1493 drvdata->sync_freq = 0x100;
1494 else
1495 drvdata->sync_freq = 0x80;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001496 drvdata->timestamp_event = 0x406F;
1497
1498 /* Overrides for Krait pass1 */
1499 if (cpu_is_krait_v1()) {
1500 /* Krait pass1 doesn't support include filtering and non-cycle
1501 * accurate tracing
1502 */
1503 drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
1504 drvdata->ctrl = 0x1000;
1505 drvdata->enable_ctrl1 = 0x1000000;
1506 for (i = 0; i < drvdata->nr_addr_cmp; i++) {
1507 drvdata->addr_val[i] = 0x0;
1508 drvdata->addr_acctype[i] = 0x0;
1509 drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
1510 }
1511 }
1512}
1513
Pratik Patel492b3012012-03-06 14:22:30 -08001514static int __devinit etm_probe(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001515{
Pratik Patele5771792011-09-17 18:33:54 -07001516 int ret;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001517 struct device *dev = &pdev->dev;
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001518 struct coresight_platform_data *pdata;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001519 struct etm_drvdata *drvdata;
Pratik Patel7831c082011-06-08 21:44:37 -07001520 struct resource *res;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001521 static int etm_count;
1522 struct coresight_desc *desc;
Pratik Patel7831c082011-06-08 21:44:37 -07001523
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001524 if (pdev->dev.of_node) {
1525 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
1526 if (IS_ERR(pdata))
1527 return PTR_ERR(pdata);
1528 pdev->dev.platform_data = pdata;
1529 }
1530
Pratik Patel4a1b2522012-06-17 15:31:15 -07001531 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
1532 if (!drvdata)
1533 return -ENOMEM;
Pratik Patel16aefdb2012-05-30 10:41:23 -07001534 drvdata->dev = &pdev->dev;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001535 platform_set_drvdata(pdev, drvdata);
Pratik Patel7831c082011-06-08 21:44:37 -07001536
Pratik Patel4a1b2522012-06-17 15:31:15 -07001537 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1538 if (!res)
1539 return -ENODEV;
1540 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
1541 if (!drvdata->base)
1542 return -ENOMEM;
1543
Pratik Patel16aefdb2012-05-30 10:41:23 -07001544 mutex_init(&drvdata->mutex);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001545 wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001546 pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
1547 PM_QOS_DEFAULT_VALUE);
Pratik Patele10a77c2012-03-20 10:35:16 -07001548
Pratik Patel4a1b2522012-06-17 15:31:15 -07001549 drvdata->clk = devm_clk_get(dev, "core_clk");
Pratik Patel16aefdb2012-05-30 10:41:23 -07001550 if (IS_ERR(drvdata->clk)) {
1551 ret = PTR_ERR(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001552 goto err0;
Pratik Patelf17b1472012-05-25 22:23:52 -07001553 }
Pratik Patel6fb38342012-06-03 14:51:38 -07001554 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
Pratik Patel7831c082011-06-08 21:44:37 -07001555 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001556 goto err0;
1557
1558 drvdata->cpu = etm_count++;
1559
Pratik Patel16aefdb2012-05-30 10:41:23 -07001560 ret = clk_prepare_enable(drvdata->clk);
Pratik Patelf17b1472012-05-25 22:23:52 -07001561 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001562 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001563 ret = etm_init_arch_data(drvdata);
Pratik Patel61de7302012-03-07 12:06:10 -08001564 if (ret)
Pratik Patel4a1b2522012-06-17 15:31:15 -07001565 goto err1;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001566 etm_init_default_data(drvdata);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001567 clk_disable_unprepare(drvdata->clk);
Pratik Patel7831c082011-06-08 21:44:37 -07001568
Pratik Patel4a1b2522012-06-17 15:31:15 -07001569 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
Pratik Patel3b0ca882012-06-01 16:54:14 -07001570 if (!desc) {
1571 ret = -ENOMEM;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001572 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001573 }
1574 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
1575 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
1576 desc->ops = &etm_cs_ops;
1577 desc->pdata = pdev->dev.platform_data;
1578 desc->dev = &pdev->dev;
1579 desc->groups = etm_attr_grps;
1580 desc->owner = THIS_MODULE;
1581 drvdata->csdev = coresight_register(desc);
1582 if (IS_ERR(drvdata->csdev)) {
1583 ret = PTR_ERR(drvdata->csdev);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001584 goto err0;
Pratik Patel3b0ca882012-06-01 16:54:14 -07001585 }
Pratik Patel3b0ca882012-06-01 16:54:14 -07001586
Pratik Patel4a1b2522012-06-17 15:31:15 -07001587 dev_info(dev, "ETM initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -07001588
Pratik Patel3b0ca882012-06-01 16:54:14 -07001589 if (boot_enable)
1590 coresight_enable(drvdata->csdev);
Pratik Patel7831c082011-06-08 21:44:37 -07001591
1592 return 0;
Pratik Patel4a1b2522012-06-17 15:31:15 -07001593err1:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001594 clk_disable_unprepare(drvdata->clk);
Pratik Patel4a1b2522012-06-17 15:31:15 -07001595err0:
Pratik Patel16aefdb2012-05-30 10:41:23 -07001596 pm_qos_remove_request(&drvdata->qos_req);
1597 wake_lock_destroy(&drvdata->wake_lock);
1598 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001599 return ret;
1600}
1601
Pratik Patelf6fe9182012-03-20 14:04:18 -07001602static int __devexit etm_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -07001603{
Pratik Patel3b0ca882012-06-01 16:54:14 -07001604 struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
1605
1606 coresight_unregister(drvdata->csdev);
Pratik Patel16aefdb2012-05-30 10:41:23 -07001607 pm_qos_remove_request(&drvdata->qos_req);
1608 wake_lock_destroy(&drvdata->wake_lock);
1609 mutex_destroy(&drvdata->mutex);
Pratik Patel7831c082011-06-08 21:44:37 -07001610 return 0;
1611}
1612
Pratik Patel9eae4822012-05-14 17:34:53 -07001613static struct of_device_id etm_match[] = {
Pratik Patel5f6d1af2012-06-13 15:48:13 -07001614 {.compatible = "arm,coresight-etm"},
Pratik Patel9eae4822012-05-14 17:34:53 -07001615 {}
1616};
1617
Pratik Patel492b3012012-03-06 14:22:30 -08001618static struct platform_driver etm_driver = {
1619 .probe = etm_probe,
Pratik Patelf6fe9182012-03-20 14:04:18 -07001620 .remove = __devexit_p(etm_remove),
Pratik Patel7831c082011-06-08 21:44:37 -07001621 .driver = {
Pratik Patel3b0ca882012-06-01 16:54:14 -07001622 .name = "coresight-etm",
Pratik Patel9eae4822012-05-14 17:34:53 -07001623 .owner = THIS_MODULE,
1624 .of_match_table = etm_match,
Pratik Patel7831c082011-06-08 21:44:37 -07001625 },
1626};
1627
Pratik Patel492b3012012-03-06 14:22:30 -08001628int __init etm_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001629{
Pratik Patel492b3012012-03-06 14:22:30 -08001630 return platform_driver_register(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001631}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001632module_init(etm_init);
Pratik Patel7831c082011-06-08 21:44:37 -07001633
Pratik Patelf6fe9182012-03-20 14:04:18 -07001634void __exit etm_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -07001635{
Pratik Patel492b3012012-03-06 14:22:30 -08001636 platform_driver_unregister(&etm_driver);
Pratik Patel7831c082011-06-08 21:44:37 -07001637}
Pratik Patelf6fe9182012-03-20 14:04:18 -07001638module_exit(etm_exit);
1639
1640MODULE_LICENSE("GPL v2");
1641MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");