xref: /openbmc/linux/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1ad0dfdfdSMathieu Poirier // SPDX-License-Identifier: GPL-2.0
2c04148e7SMathieu Poirier /*
3c04148e7SMathieu Poirier  * Copyright(C) 2015 Linaro Limited. All rights reserved.
4c04148e7SMathieu Poirier  * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
5c04148e7SMathieu Poirier  */
6c04148e7SMathieu Poirier 
77bd50ccfSMathieu Poirier #include <linux/pid_namespace.h>
8c04148e7SMathieu Poirier #include <linux/pm_runtime.h>
9c04148e7SMathieu Poirier #include <linux/sysfs.h>
10c04148e7SMathieu Poirier #include "coresight-etm.h"
112b7adc46SMathieu Poirier #include "coresight-priv.h"
12c04148e7SMathieu Poirier 
nr_addr_cmp_show(struct device * dev,struct device_attribute * attr,char * buf)13c04148e7SMathieu Poirier static ssize_t nr_addr_cmp_show(struct device *dev,
14c04148e7SMathieu Poirier 				struct device_attribute *attr, char *buf)
15c04148e7SMathieu Poirier {
16c04148e7SMathieu Poirier 	unsigned long val;
17c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
18c04148e7SMathieu Poirier 
19c04148e7SMathieu Poirier 	val = drvdata->nr_addr_cmp;
20c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
21c04148e7SMathieu Poirier }
22c04148e7SMathieu Poirier static DEVICE_ATTR_RO(nr_addr_cmp);
23c04148e7SMathieu Poirier 
nr_cntr_show(struct device * dev,struct device_attribute * attr,char * buf)24c04148e7SMathieu Poirier static ssize_t nr_cntr_show(struct device *dev,
25c04148e7SMathieu Poirier 			    struct device_attribute *attr, char *buf)
26c04148e7SMathieu Poirier {	unsigned long val;
27c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
28c04148e7SMathieu Poirier 
29c04148e7SMathieu Poirier 	val = drvdata->nr_cntr;
30c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
31c04148e7SMathieu Poirier }
32c04148e7SMathieu Poirier static DEVICE_ATTR_RO(nr_cntr);
33c04148e7SMathieu Poirier 
nr_ctxid_cmp_show(struct device * dev,struct device_attribute * attr,char * buf)34c04148e7SMathieu Poirier static ssize_t nr_ctxid_cmp_show(struct device *dev,
35c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
36c04148e7SMathieu Poirier {
37c04148e7SMathieu Poirier 	unsigned long val;
38c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
39c04148e7SMathieu Poirier 
40c04148e7SMathieu Poirier 	val = drvdata->nr_ctxid_cmp;
41c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
42c04148e7SMathieu Poirier }
43c04148e7SMathieu Poirier static DEVICE_ATTR_RO(nr_ctxid_cmp);
44c04148e7SMathieu Poirier 
etmsr_show(struct device * dev,struct device_attribute * attr,char * buf)45c04148e7SMathieu Poirier static ssize_t etmsr_show(struct device *dev,
46c04148e7SMathieu Poirier 			  struct device_attribute *attr, char *buf)
47c04148e7SMathieu Poirier {
48c04148e7SMathieu Poirier 	unsigned long flags, val;
49c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
50c04148e7SMathieu Poirier 
51aaff7623SSuzuki K Poulose 	pm_runtime_get_sync(dev->parent);
52c04148e7SMathieu Poirier 	spin_lock_irqsave(&drvdata->spinlock, flags);
53c04148e7SMathieu Poirier 	CS_UNLOCK(drvdata->base);
54c04148e7SMathieu Poirier 
55c04148e7SMathieu Poirier 	val = etm_readl(drvdata, ETMSR);
56c04148e7SMathieu Poirier 
57c04148e7SMathieu Poirier 	CS_LOCK(drvdata->base);
58c04148e7SMathieu Poirier 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
59aaff7623SSuzuki K Poulose 	pm_runtime_put(dev->parent);
60c04148e7SMathieu Poirier 
61c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
62c04148e7SMathieu Poirier }
63c04148e7SMathieu Poirier static DEVICE_ATTR_RO(etmsr);
64c04148e7SMathieu Poirier 
reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)65c04148e7SMathieu Poirier static ssize_t reset_store(struct device *dev,
66c04148e7SMathieu Poirier 			   struct device_attribute *attr,
67c04148e7SMathieu Poirier 			   const char *buf, size_t size)
68c04148e7SMathieu Poirier {
69c04148e7SMathieu Poirier 	int i, ret;
70c04148e7SMathieu Poirier 	unsigned long val;
71c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
721925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
73c04148e7SMathieu Poirier 
74c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
75c04148e7SMathieu Poirier 	if (ret)
76c04148e7SMathieu Poirier 		return ret;
77c04148e7SMathieu Poirier 
78c04148e7SMathieu Poirier 	if (val) {
79c04148e7SMathieu Poirier 		spin_lock(&drvdata->spinlock);
801925a470SMathieu Poirier 		memset(config, 0, sizeof(struct etm_config));
811925a470SMathieu Poirier 		config->mode = ETM_MODE_EXCLUDE;
821925a470SMathieu Poirier 		config->trigger_event = ETM_DEFAULT_EVENT_VAL;
83c04148e7SMathieu Poirier 		for (i = 0; i < drvdata->nr_addr_cmp; i++) {
841925a470SMathieu Poirier 			config->addr_type[i] = ETM_ADDR_TYPE_NONE;
85c04148e7SMathieu Poirier 		}
86c04148e7SMathieu Poirier 
871925a470SMathieu Poirier 		etm_set_default(config);
88*9edf2910SMike Leach 		etm_release_trace_id(drvdata);
89c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
90c04148e7SMathieu Poirier 	}
91c04148e7SMathieu Poirier 
92c04148e7SMathieu Poirier 	return size;
93c04148e7SMathieu Poirier }
94c04148e7SMathieu Poirier static DEVICE_ATTR_WO(reset);
95c04148e7SMathieu Poirier 
mode_show(struct device * dev,struct device_attribute * attr,char * buf)96c04148e7SMathieu Poirier static ssize_t mode_show(struct device *dev,
97c04148e7SMathieu Poirier 			 struct device_attribute *attr, char *buf)
98c04148e7SMathieu Poirier {
99c04148e7SMathieu Poirier 	unsigned long val;
100c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1011925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
102c04148e7SMathieu Poirier 
1031925a470SMathieu Poirier 	val = config->mode;
104c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
105c04148e7SMathieu Poirier }
106c04148e7SMathieu Poirier 
mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)107c04148e7SMathieu Poirier static ssize_t mode_store(struct device *dev,
108c04148e7SMathieu Poirier 			  struct device_attribute *attr,
109c04148e7SMathieu Poirier 			  const char *buf, size_t size)
110c04148e7SMathieu Poirier {
111c04148e7SMathieu Poirier 	int ret;
112c04148e7SMathieu Poirier 	unsigned long val;
113c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1141925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
115c04148e7SMathieu Poirier 
116c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
117c04148e7SMathieu Poirier 	if (ret)
118c04148e7SMathieu Poirier 		return ret;
119c04148e7SMathieu Poirier 
120c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
1211925a470SMathieu Poirier 	config->mode = val & ETM_MODE_ALL;
122c04148e7SMathieu Poirier 
1231925a470SMathieu Poirier 	if (config->mode & ETM_MODE_EXCLUDE)
1241925a470SMathieu Poirier 		config->enable_ctrl1 |= ETMTECR1_INC_EXC;
125c04148e7SMathieu Poirier 	else
1261925a470SMathieu Poirier 		config->enable_ctrl1 &= ~ETMTECR1_INC_EXC;
127c04148e7SMathieu Poirier 
1281925a470SMathieu Poirier 	if (config->mode & ETM_MODE_CYCACC)
1291925a470SMathieu Poirier 		config->ctrl |= ETMCR_CYC_ACC;
130c04148e7SMathieu Poirier 	else
1311925a470SMathieu Poirier 		config->ctrl &= ~ETMCR_CYC_ACC;
132c04148e7SMathieu Poirier 
1331925a470SMathieu Poirier 	if (config->mode & ETM_MODE_STALL) {
134c04148e7SMathieu Poirier 		if (!(drvdata->etmccr & ETMCCR_FIFOFULL)) {
135aaff7623SSuzuki K Poulose 			dev_warn(dev, "stall mode not supported\n");
136c04148e7SMathieu Poirier 			ret = -EINVAL;
137c04148e7SMathieu Poirier 			goto err_unlock;
138c04148e7SMathieu Poirier 		}
1391925a470SMathieu Poirier 		config->ctrl |= ETMCR_STALL_MODE;
140c04148e7SMathieu Poirier 	} else
1411925a470SMathieu Poirier 		config->ctrl &= ~ETMCR_STALL_MODE;
142c04148e7SMathieu Poirier 
1431925a470SMathieu Poirier 	if (config->mode & ETM_MODE_TIMESTAMP) {
144c04148e7SMathieu Poirier 		if (!(drvdata->etmccer & ETMCCER_TIMESTAMP)) {
145aaff7623SSuzuki K Poulose 			dev_warn(dev, "timestamp not supported\n");
146c04148e7SMathieu Poirier 			ret = -EINVAL;
147c04148e7SMathieu Poirier 			goto err_unlock;
148c04148e7SMathieu Poirier 		}
1491925a470SMathieu Poirier 		config->ctrl |= ETMCR_TIMESTAMP_EN;
150c04148e7SMathieu Poirier 	} else
1511925a470SMathieu Poirier 		config->ctrl &= ~ETMCR_TIMESTAMP_EN;
152c04148e7SMathieu Poirier 
1531925a470SMathieu Poirier 	if (config->mode & ETM_MODE_CTXID)
1541925a470SMathieu Poirier 		config->ctrl |= ETMCR_CTXID_SIZE;
155c04148e7SMathieu Poirier 	else
1561925a470SMathieu Poirier 		config->ctrl &= ~ETMCR_CTXID_SIZE;
1572127154dSMathieu Poirier 
158a39f841aSMuhammad Abdul WAHAB 	if (config->mode & ETM_MODE_BBROAD)
159a39f841aSMuhammad Abdul WAHAB 		config->ctrl |= ETMCR_BRANCH_BROADCAST;
160a39f841aSMuhammad Abdul WAHAB 	else
161a39f841aSMuhammad Abdul WAHAB 		config->ctrl &= ~ETMCR_BRANCH_BROADCAST;
162a39f841aSMuhammad Abdul WAHAB 
163a39f841aSMuhammad Abdul WAHAB 	if (config->mode & ETM_MODE_RET_STACK)
164a39f841aSMuhammad Abdul WAHAB 		config->ctrl |= ETMCR_RETURN_STACK;
165a39f841aSMuhammad Abdul WAHAB 	else
166a39f841aSMuhammad Abdul WAHAB 		config->ctrl &= ~ETMCR_RETURN_STACK;
167a39f841aSMuhammad Abdul WAHAB 
1682127154dSMathieu Poirier 	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
1692127154dSMathieu Poirier 		etm_config_trace_mode(config);
1702127154dSMathieu Poirier 
171c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
172c04148e7SMathieu Poirier 
173c04148e7SMathieu Poirier 	return size;
174c04148e7SMathieu Poirier 
175c04148e7SMathieu Poirier err_unlock:
176c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
177c04148e7SMathieu Poirier 	return ret;
178c04148e7SMathieu Poirier }
179c04148e7SMathieu Poirier static DEVICE_ATTR_RW(mode);
180c04148e7SMathieu Poirier 
trigger_event_show(struct device * dev,struct device_attribute * attr,char * buf)181c04148e7SMathieu Poirier static ssize_t trigger_event_show(struct device *dev,
182c04148e7SMathieu Poirier 				  struct device_attribute *attr, char *buf)
183c04148e7SMathieu Poirier {
184c04148e7SMathieu Poirier 	unsigned long val;
185c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1861925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
187c04148e7SMathieu Poirier 
1881925a470SMathieu Poirier 	val = config->trigger_event;
189c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
190c04148e7SMathieu Poirier }
191c04148e7SMathieu Poirier 
trigger_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)192c04148e7SMathieu Poirier static ssize_t trigger_event_store(struct device *dev,
193c04148e7SMathieu Poirier 				   struct device_attribute *attr,
194c04148e7SMathieu Poirier 				   const char *buf, size_t size)
195c04148e7SMathieu Poirier {
196c04148e7SMathieu Poirier 	int ret;
197c04148e7SMathieu Poirier 	unsigned long val;
198c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1991925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
200c04148e7SMathieu Poirier 
201c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
202c04148e7SMathieu Poirier 	if (ret)
203c04148e7SMathieu Poirier 		return ret;
204c04148e7SMathieu Poirier 
2051925a470SMathieu Poirier 	config->trigger_event = val & ETM_EVENT_MASK;
206c04148e7SMathieu Poirier 
207c04148e7SMathieu Poirier 	return size;
208c04148e7SMathieu Poirier }
209c04148e7SMathieu Poirier static DEVICE_ATTR_RW(trigger_event);
210c04148e7SMathieu Poirier 
enable_event_show(struct device * dev,struct device_attribute * attr,char * buf)211c04148e7SMathieu Poirier static ssize_t enable_event_show(struct device *dev,
212c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
213c04148e7SMathieu Poirier {
214c04148e7SMathieu Poirier 	unsigned long val;
215c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2161925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
217c04148e7SMathieu Poirier 
2181925a470SMathieu Poirier 	val = config->enable_event;
219c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
220c04148e7SMathieu Poirier }
221c04148e7SMathieu Poirier 
enable_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)222c04148e7SMathieu Poirier static ssize_t enable_event_store(struct device *dev,
223c04148e7SMathieu Poirier 				  struct device_attribute *attr,
224c04148e7SMathieu Poirier 				  const char *buf, size_t size)
225c04148e7SMathieu Poirier {
226c04148e7SMathieu Poirier 	int ret;
227c04148e7SMathieu Poirier 	unsigned long val;
228c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2291925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
230c04148e7SMathieu Poirier 
231c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
232c04148e7SMathieu Poirier 	if (ret)
233c04148e7SMathieu Poirier 		return ret;
234c04148e7SMathieu Poirier 
2351925a470SMathieu Poirier 	config->enable_event = val & ETM_EVENT_MASK;
236c04148e7SMathieu Poirier 
237c04148e7SMathieu Poirier 	return size;
238c04148e7SMathieu Poirier }
239c04148e7SMathieu Poirier static DEVICE_ATTR_RW(enable_event);
240c04148e7SMathieu Poirier 
fifofull_level_show(struct device * dev,struct device_attribute * attr,char * buf)241c04148e7SMathieu Poirier static ssize_t fifofull_level_show(struct device *dev,
242c04148e7SMathieu Poirier 				   struct device_attribute *attr, char *buf)
243c04148e7SMathieu Poirier {
244c04148e7SMathieu Poirier 	unsigned long val;
245c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2461925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
247c04148e7SMathieu Poirier 
2481925a470SMathieu Poirier 	val = config->fifofull_level;
249c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
250c04148e7SMathieu Poirier }
251c04148e7SMathieu Poirier 
fifofull_level_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)252c04148e7SMathieu Poirier static ssize_t fifofull_level_store(struct device *dev,
253c04148e7SMathieu Poirier 				    struct device_attribute *attr,
254c04148e7SMathieu Poirier 				    const char *buf, size_t size)
255c04148e7SMathieu Poirier {
256c04148e7SMathieu Poirier 	int ret;
257c04148e7SMathieu Poirier 	unsigned long val;
258c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2591925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
260c04148e7SMathieu Poirier 
261c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
262c04148e7SMathieu Poirier 	if (ret)
263c04148e7SMathieu Poirier 		return ret;
264c04148e7SMathieu Poirier 
2651925a470SMathieu Poirier 	config->fifofull_level = val;
266c04148e7SMathieu Poirier 
267c04148e7SMathieu Poirier 	return size;
268c04148e7SMathieu Poirier }
269c04148e7SMathieu Poirier static DEVICE_ATTR_RW(fifofull_level);
270c04148e7SMathieu Poirier 
addr_idx_show(struct device * dev,struct device_attribute * attr,char * buf)271c04148e7SMathieu Poirier static ssize_t addr_idx_show(struct device *dev,
272c04148e7SMathieu Poirier 			     struct device_attribute *attr, char *buf)
273c04148e7SMathieu Poirier {
274c04148e7SMathieu Poirier 	unsigned long val;
275c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2761925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
277c04148e7SMathieu Poirier 
2781925a470SMathieu Poirier 	val = config->addr_idx;
279c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
280c04148e7SMathieu Poirier }
281c04148e7SMathieu Poirier 
addr_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)282c04148e7SMathieu Poirier static ssize_t addr_idx_store(struct device *dev,
283c04148e7SMathieu Poirier 			      struct device_attribute *attr,
284c04148e7SMathieu Poirier 			      const char *buf, size_t size)
285c04148e7SMathieu Poirier {
286c04148e7SMathieu Poirier 	int ret;
287c04148e7SMathieu Poirier 	unsigned long val;
288c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2891925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
290c04148e7SMathieu Poirier 
291c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
292c04148e7SMathieu Poirier 	if (ret)
293c04148e7SMathieu Poirier 		return ret;
294c04148e7SMathieu Poirier 
295c04148e7SMathieu Poirier 	if (val >= drvdata->nr_addr_cmp)
296c04148e7SMathieu Poirier 		return -EINVAL;
297c04148e7SMathieu Poirier 
298c04148e7SMathieu Poirier 	/*
299c04148e7SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
300c04148e7SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
301c04148e7SMathieu Poirier 	 */
302c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
3031925a470SMathieu Poirier 	config->addr_idx = val;
304c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
305c04148e7SMathieu Poirier 
306c04148e7SMathieu Poirier 	return size;
307c04148e7SMathieu Poirier }
308c04148e7SMathieu Poirier static DEVICE_ATTR_RW(addr_idx);
309c04148e7SMathieu Poirier 
addr_single_show(struct device * dev,struct device_attribute * attr,char * buf)310c04148e7SMathieu Poirier static ssize_t addr_single_show(struct device *dev,
311c04148e7SMathieu Poirier 				struct device_attribute *attr, char *buf)
312c04148e7SMathieu Poirier {
313c04148e7SMathieu Poirier 	u8 idx;
314c04148e7SMathieu Poirier 	unsigned long val;
315c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3161925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
317c04148e7SMathieu Poirier 
318c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
3191925a470SMathieu Poirier 	idx = config->addr_idx;
3201925a470SMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
3211925a470SMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
322c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
323c04148e7SMathieu Poirier 		return -EINVAL;
324c04148e7SMathieu Poirier 	}
325c04148e7SMathieu Poirier 
3261925a470SMathieu Poirier 	val = config->addr_val[idx];
327c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
328c04148e7SMathieu Poirier 
329c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
330c04148e7SMathieu Poirier }
331c04148e7SMathieu Poirier 
addr_single_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)332c04148e7SMathieu Poirier static ssize_t addr_single_store(struct device *dev,
333c04148e7SMathieu Poirier 				 struct device_attribute *attr,
334c04148e7SMathieu Poirier 				 const char *buf, size_t size)
335c04148e7SMathieu Poirier {
336c04148e7SMathieu Poirier 	u8 idx;
337c04148e7SMathieu Poirier 	int ret;
338c04148e7SMathieu Poirier 	unsigned long val;
339c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3401925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
341c04148e7SMathieu Poirier 
342c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
343c04148e7SMathieu Poirier 	if (ret)
344c04148e7SMathieu Poirier 		return ret;
345c04148e7SMathieu Poirier 
346c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
3471925a470SMathieu Poirier 	idx = config->addr_idx;
3481925a470SMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
3491925a470SMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
350c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
351c04148e7SMathieu Poirier 		return -EINVAL;
352c04148e7SMathieu Poirier 	}
353c04148e7SMathieu Poirier 
3541925a470SMathieu Poirier 	config->addr_val[idx] = val;
3551925a470SMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
356c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
357c04148e7SMathieu Poirier 
358c04148e7SMathieu Poirier 	return size;
359c04148e7SMathieu Poirier }
360c04148e7SMathieu Poirier static DEVICE_ATTR_RW(addr_single);
361c04148e7SMathieu Poirier 
addr_range_show(struct device * dev,struct device_attribute * attr,char * buf)362c04148e7SMathieu Poirier static ssize_t addr_range_show(struct device *dev,
363c04148e7SMathieu Poirier 			       struct device_attribute *attr, char *buf)
364c04148e7SMathieu Poirier {
365c04148e7SMathieu Poirier 	u8 idx;
366c04148e7SMathieu Poirier 	unsigned long val1, val2;
367c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3681925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
369c04148e7SMathieu Poirier 
370c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
3711925a470SMathieu Poirier 	idx = config->addr_idx;
372c04148e7SMathieu Poirier 	if (idx % 2 != 0) {
373c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
374c04148e7SMathieu Poirier 		return -EPERM;
375c04148e7SMathieu Poirier 	}
3761925a470SMathieu Poirier 	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
3771925a470SMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
3781925a470SMathieu Poirier 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
3791925a470SMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
380c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
381c04148e7SMathieu Poirier 		return -EPERM;
382c04148e7SMathieu Poirier 	}
383c04148e7SMathieu Poirier 
3841925a470SMathieu Poirier 	val1 = config->addr_val[idx];
3851925a470SMathieu Poirier 	val2 = config->addr_val[idx + 1];
386c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
387c04148e7SMathieu Poirier 
388c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx %#lx\n", val1, val2);
389c04148e7SMathieu Poirier }
390c04148e7SMathieu Poirier 
addr_range_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)391c04148e7SMathieu Poirier static ssize_t addr_range_store(struct device *dev,
392c04148e7SMathieu Poirier 			      struct device_attribute *attr,
393c04148e7SMathieu Poirier 			      const char *buf, size_t size)
394c04148e7SMathieu Poirier {
395c04148e7SMathieu Poirier 	u8 idx;
396c04148e7SMathieu Poirier 	unsigned long val1, val2;
397c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3981925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
399c04148e7SMathieu Poirier 
400c04148e7SMathieu Poirier 	if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
401c04148e7SMathieu Poirier 		return -EINVAL;
402c04148e7SMathieu Poirier 	/* Lower address comparator cannot have a higher address value */
403c04148e7SMathieu Poirier 	if (val1 > val2)
404c04148e7SMathieu Poirier 		return -EINVAL;
405c04148e7SMathieu Poirier 
406c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
4071925a470SMathieu Poirier 	idx = config->addr_idx;
408c04148e7SMathieu Poirier 	if (idx % 2 != 0) {
409c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
410c04148e7SMathieu Poirier 		return -EPERM;
411c04148e7SMathieu Poirier 	}
4121925a470SMathieu Poirier 	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
4131925a470SMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
4141925a470SMathieu Poirier 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
4151925a470SMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
416c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
417c04148e7SMathieu Poirier 		return -EPERM;
418c04148e7SMathieu Poirier 	}
419c04148e7SMathieu Poirier 
4201925a470SMathieu Poirier 	config->addr_val[idx] = val1;
4211925a470SMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
4221925a470SMathieu Poirier 	config->addr_val[idx + 1] = val2;
4231925a470SMathieu Poirier 	config->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
4241925a470SMathieu Poirier 	config->enable_ctrl1 |= (1 << (idx/2));
425c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
426c04148e7SMathieu Poirier 
427c04148e7SMathieu Poirier 	return size;
428c04148e7SMathieu Poirier }
429c04148e7SMathieu Poirier static DEVICE_ATTR_RW(addr_range);
430c04148e7SMathieu Poirier 
addr_start_show(struct device * dev,struct device_attribute * attr,char * buf)431c04148e7SMathieu Poirier static ssize_t addr_start_show(struct device *dev,
432c04148e7SMathieu Poirier 			       struct device_attribute *attr, char *buf)
433c04148e7SMathieu Poirier {
434c04148e7SMathieu Poirier 	u8 idx;
435c04148e7SMathieu Poirier 	unsigned long val;
436c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
4371925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
438c04148e7SMathieu Poirier 
439c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
4401925a470SMathieu Poirier 	idx = config->addr_idx;
4411925a470SMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
4421925a470SMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
443c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
444c04148e7SMathieu Poirier 		return -EPERM;
445c04148e7SMathieu Poirier 	}
446c04148e7SMathieu Poirier 
4471925a470SMathieu Poirier 	val = config->addr_val[idx];
448c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
449c04148e7SMathieu Poirier 
450c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
451c04148e7SMathieu Poirier }
452c04148e7SMathieu Poirier 
addr_start_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)453c04148e7SMathieu Poirier static ssize_t addr_start_store(struct device *dev,
454c04148e7SMathieu Poirier 				struct device_attribute *attr,
455c04148e7SMathieu Poirier 				const char *buf, size_t size)
456c04148e7SMathieu Poirier {
457c04148e7SMathieu Poirier 	u8 idx;
458c04148e7SMathieu Poirier 	int ret;
459c04148e7SMathieu Poirier 	unsigned long val;
460c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
4611925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
462c04148e7SMathieu Poirier 
463c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
464c04148e7SMathieu Poirier 	if (ret)
465c04148e7SMathieu Poirier 		return ret;
466c04148e7SMathieu Poirier 
467c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
4681925a470SMathieu Poirier 	idx = config->addr_idx;
4691925a470SMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
4701925a470SMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
471c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
472c04148e7SMathieu Poirier 		return -EPERM;
473c04148e7SMathieu Poirier 	}
474c04148e7SMathieu Poirier 
4751925a470SMathieu Poirier 	config->addr_val[idx] = val;
4761925a470SMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_START;
4771925a470SMathieu Poirier 	config->startstop_ctrl |= (1 << idx);
4784bc500efSJames Clark 	config->enable_ctrl1 |= ETMTECR1_START_STOP;
479c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
480c04148e7SMathieu Poirier 
481c04148e7SMathieu Poirier 	return size;
482c04148e7SMathieu Poirier }
483c04148e7SMathieu Poirier static DEVICE_ATTR_RW(addr_start);
484c04148e7SMathieu Poirier 
addr_stop_show(struct device * dev,struct device_attribute * attr,char * buf)485c04148e7SMathieu Poirier static ssize_t addr_stop_show(struct device *dev,
486c04148e7SMathieu Poirier 			      struct device_attribute *attr, char *buf)
487c04148e7SMathieu Poirier {
488c04148e7SMathieu Poirier 	u8 idx;
489c04148e7SMathieu Poirier 	unsigned long val;
490c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
4911925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
492c04148e7SMathieu Poirier 
493c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
4941925a470SMathieu Poirier 	idx = config->addr_idx;
4951925a470SMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
4961925a470SMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
497c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
498c04148e7SMathieu Poirier 		return -EPERM;
499c04148e7SMathieu Poirier 	}
500c04148e7SMathieu Poirier 
5011925a470SMathieu Poirier 	val = config->addr_val[idx];
502c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
503c04148e7SMathieu Poirier 
504c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
505c04148e7SMathieu Poirier }
506c04148e7SMathieu Poirier 
addr_stop_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)507c04148e7SMathieu Poirier static ssize_t addr_stop_store(struct device *dev,
508c04148e7SMathieu Poirier 			       struct device_attribute *attr,
509c04148e7SMathieu Poirier 			       const char *buf, size_t size)
510c04148e7SMathieu Poirier {
511c04148e7SMathieu Poirier 	u8 idx;
512c04148e7SMathieu Poirier 	int ret;
513c04148e7SMathieu Poirier 	unsigned long val;
514c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
5151925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
516c04148e7SMathieu Poirier 
517c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
518c04148e7SMathieu Poirier 	if (ret)
519c04148e7SMathieu Poirier 		return ret;
520c04148e7SMathieu Poirier 
521c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
5221925a470SMathieu Poirier 	idx = config->addr_idx;
5231925a470SMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
5241925a470SMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
525c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
526c04148e7SMathieu Poirier 		return -EPERM;
527c04148e7SMathieu Poirier 	}
528c04148e7SMathieu Poirier 
5291925a470SMathieu Poirier 	config->addr_val[idx] = val;
5301925a470SMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_STOP;
5311925a470SMathieu Poirier 	config->startstop_ctrl |= (1 << (idx + 16));
5321925a470SMathieu Poirier 	config->enable_ctrl1 |= ETMTECR1_START_STOP;
533c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
534c04148e7SMathieu Poirier 
535c04148e7SMathieu Poirier 	return size;
536c04148e7SMathieu Poirier }
537c04148e7SMathieu Poirier static DEVICE_ATTR_RW(addr_stop);
538c04148e7SMathieu Poirier 
addr_acctype_show(struct device * dev,struct device_attribute * attr,char * buf)539c04148e7SMathieu Poirier static ssize_t addr_acctype_show(struct device *dev,
540c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
541c04148e7SMathieu Poirier {
542c04148e7SMathieu Poirier 	unsigned long val;
543c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
5441925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
545c04148e7SMathieu Poirier 
546c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
5471925a470SMathieu Poirier 	val = config->addr_acctype[config->addr_idx];
548c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
549c04148e7SMathieu Poirier 
550c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
551c04148e7SMathieu Poirier }
552c04148e7SMathieu Poirier 
addr_acctype_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)553c04148e7SMathieu Poirier static ssize_t addr_acctype_store(struct device *dev,
554c04148e7SMathieu Poirier 				  struct device_attribute *attr,
555c04148e7SMathieu Poirier 				  const char *buf, size_t size)
556c04148e7SMathieu Poirier {
557c04148e7SMathieu Poirier 	int ret;
558c04148e7SMathieu Poirier 	unsigned long val;
559c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
5601925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
561c04148e7SMathieu Poirier 
562c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
563c04148e7SMathieu Poirier 	if (ret)
564c04148e7SMathieu Poirier 		return ret;
565c04148e7SMathieu Poirier 
566c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
5671925a470SMathieu Poirier 	config->addr_acctype[config->addr_idx] = val;
568c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
569c04148e7SMathieu Poirier 
570c04148e7SMathieu Poirier 	return size;
571c04148e7SMathieu Poirier }
572c04148e7SMathieu Poirier static DEVICE_ATTR_RW(addr_acctype);
573c04148e7SMathieu Poirier 
cntr_idx_show(struct device * dev,struct device_attribute * attr,char * buf)574c04148e7SMathieu Poirier static ssize_t cntr_idx_show(struct device *dev,
575c04148e7SMathieu Poirier 			     struct device_attribute *attr, char *buf)
576c04148e7SMathieu Poirier {
577c04148e7SMathieu Poirier 	unsigned long val;
578c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
5791925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
580c04148e7SMathieu Poirier 
5811925a470SMathieu Poirier 	val = config->cntr_idx;
582c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
583c04148e7SMathieu Poirier }
584c04148e7SMathieu Poirier 
cntr_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)585c04148e7SMathieu Poirier static ssize_t cntr_idx_store(struct device *dev,
586c04148e7SMathieu Poirier 			      struct device_attribute *attr,
587c04148e7SMathieu Poirier 			      const char *buf, size_t size)
588c04148e7SMathieu Poirier {
589c04148e7SMathieu Poirier 	int ret;
590c04148e7SMathieu Poirier 	unsigned long val;
591c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
5921925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
593c04148e7SMathieu Poirier 
594c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
595c04148e7SMathieu Poirier 	if (ret)
596c04148e7SMathieu Poirier 		return ret;
597c04148e7SMathieu Poirier 
598c04148e7SMathieu Poirier 	if (val >= drvdata->nr_cntr)
599c04148e7SMathieu Poirier 		return -EINVAL;
600c04148e7SMathieu Poirier 	/*
601c04148e7SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
602c04148e7SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
603c04148e7SMathieu Poirier 	 */
604c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
6051925a470SMathieu Poirier 	config->cntr_idx = val;
606c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
607c04148e7SMathieu Poirier 
608c04148e7SMathieu Poirier 	return size;
609c04148e7SMathieu Poirier }
610c04148e7SMathieu Poirier static DEVICE_ATTR_RW(cntr_idx);
611c04148e7SMathieu Poirier 
cntr_rld_val_show(struct device * dev,struct device_attribute * attr,char * buf)612c04148e7SMathieu Poirier static ssize_t cntr_rld_val_show(struct device *dev,
613c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
614c04148e7SMathieu Poirier {
615c04148e7SMathieu Poirier 	unsigned long val;
616c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
6171925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
618c04148e7SMathieu Poirier 
619c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
6201925a470SMathieu Poirier 	val = config->cntr_rld_val[config->cntr_idx];
621c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
622c04148e7SMathieu Poirier 
623c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
624c04148e7SMathieu Poirier }
625c04148e7SMathieu Poirier 
cntr_rld_val_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)626c04148e7SMathieu Poirier static ssize_t cntr_rld_val_store(struct device *dev,
627c04148e7SMathieu Poirier 				  struct device_attribute *attr,
628c04148e7SMathieu Poirier 				  const char *buf, size_t size)
629c04148e7SMathieu Poirier {
630c04148e7SMathieu Poirier 	int ret;
631c04148e7SMathieu Poirier 	unsigned long val;
632c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
6331925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
634c04148e7SMathieu Poirier 
635c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
636c04148e7SMathieu Poirier 	if (ret)
637c04148e7SMathieu Poirier 		return ret;
638c04148e7SMathieu Poirier 
639c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
6401925a470SMathieu Poirier 	config->cntr_rld_val[config->cntr_idx] = val;
641c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
642c04148e7SMathieu Poirier 
643c04148e7SMathieu Poirier 	return size;
644c04148e7SMathieu Poirier }
645c04148e7SMathieu Poirier static DEVICE_ATTR_RW(cntr_rld_val);
646c04148e7SMathieu Poirier 
cntr_event_show(struct device * dev,struct device_attribute * attr,char * buf)647c04148e7SMathieu Poirier static ssize_t cntr_event_show(struct device *dev,
648c04148e7SMathieu Poirier 			       struct device_attribute *attr, char *buf)
649c04148e7SMathieu Poirier {
650c04148e7SMathieu Poirier 	unsigned long val;
651c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
6521925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
653c04148e7SMathieu Poirier 
654c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
6551925a470SMathieu Poirier 	val = config->cntr_event[config->cntr_idx];
656c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
657c04148e7SMathieu Poirier 
658c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
659c04148e7SMathieu Poirier }
660c04148e7SMathieu Poirier 
cntr_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)661c04148e7SMathieu Poirier static ssize_t cntr_event_store(struct device *dev,
662c04148e7SMathieu Poirier 				struct device_attribute *attr,
663c04148e7SMathieu Poirier 				const char *buf, size_t size)
664c04148e7SMathieu Poirier {
665c04148e7SMathieu Poirier 	int ret;
666c04148e7SMathieu Poirier 	unsigned long val;
667c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
6681925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
669c04148e7SMathieu Poirier 
670c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
671c04148e7SMathieu Poirier 	if (ret)
672c04148e7SMathieu Poirier 		return ret;
673c04148e7SMathieu Poirier 
674c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
6751925a470SMathieu Poirier 	config->cntr_event[config->cntr_idx] = val & ETM_EVENT_MASK;
676c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
677c04148e7SMathieu Poirier 
678c04148e7SMathieu Poirier 	return size;
679c04148e7SMathieu Poirier }
680c04148e7SMathieu Poirier static DEVICE_ATTR_RW(cntr_event);
681c04148e7SMathieu Poirier 
cntr_rld_event_show(struct device * dev,struct device_attribute * attr,char * buf)682c04148e7SMathieu Poirier static ssize_t cntr_rld_event_show(struct device *dev,
683c04148e7SMathieu Poirier 				   struct device_attribute *attr, char *buf)
684c04148e7SMathieu Poirier {
685c04148e7SMathieu Poirier 	unsigned long val;
686c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
6871925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
688c04148e7SMathieu Poirier 
689c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
6901925a470SMathieu Poirier 	val = config->cntr_rld_event[config->cntr_idx];
691c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
692c04148e7SMathieu Poirier 
693c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
694c04148e7SMathieu Poirier }
695c04148e7SMathieu Poirier 
cntr_rld_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)696c04148e7SMathieu Poirier static ssize_t cntr_rld_event_store(struct device *dev,
697c04148e7SMathieu Poirier 				    struct device_attribute *attr,
698c04148e7SMathieu Poirier 				    const char *buf, size_t size)
699c04148e7SMathieu Poirier {
700c04148e7SMathieu Poirier 	int ret;
701c04148e7SMathieu Poirier 	unsigned long val;
702c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
7031925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
704c04148e7SMathieu Poirier 
705c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
706c04148e7SMathieu Poirier 	if (ret)
707c04148e7SMathieu Poirier 		return ret;
708c04148e7SMathieu Poirier 
709c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
7101925a470SMathieu Poirier 	config->cntr_rld_event[config->cntr_idx] = val & ETM_EVENT_MASK;
711c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
712c04148e7SMathieu Poirier 
713c04148e7SMathieu Poirier 	return size;
714c04148e7SMathieu Poirier }
715c04148e7SMathieu Poirier static DEVICE_ATTR_RW(cntr_rld_event);
716c04148e7SMathieu Poirier 
cntr_val_show(struct device * dev,struct device_attribute * attr,char * buf)717c04148e7SMathieu Poirier static ssize_t cntr_val_show(struct device *dev,
718c04148e7SMathieu Poirier 			     struct device_attribute *attr, char *buf)
719c04148e7SMathieu Poirier {
720c04148e7SMathieu Poirier 	int i, ret = 0;
721c04148e7SMathieu Poirier 	u32 val;
722c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
7231925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
724c04148e7SMathieu Poirier 
72522fd532eSMathieu Poirier 	if (!local_read(&drvdata->mode)) {
726c04148e7SMathieu Poirier 		spin_lock(&drvdata->spinlock);
727c04148e7SMathieu Poirier 		for (i = 0; i < drvdata->nr_cntr; i++)
728c04148e7SMathieu Poirier 			ret += sprintf(buf, "counter %d: %x\n",
7291925a470SMathieu Poirier 				       i, config->cntr_val[i]);
730c04148e7SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
731c04148e7SMathieu Poirier 		return ret;
732c04148e7SMathieu Poirier 	}
733c04148e7SMathieu Poirier 
734c04148e7SMathieu Poirier 	for (i = 0; i < drvdata->nr_cntr; i++) {
735c04148e7SMathieu Poirier 		val = etm_readl(drvdata, ETMCNTVRn(i));
736c04148e7SMathieu Poirier 		ret += sprintf(buf, "counter %d: %x\n", i, val);
737c04148e7SMathieu Poirier 	}
738c04148e7SMathieu Poirier 
739c04148e7SMathieu Poirier 	return ret;
740c04148e7SMathieu Poirier }
741c04148e7SMathieu Poirier 
cntr_val_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)742c04148e7SMathieu Poirier static ssize_t cntr_val_store(struct device *dev,
743c04148e7SMathieu Poirier 			      struct device_attribute *attr,
744c04148e7SMathieu Poirier 			      const char *buf, size_t size)
745c04148e7SMathieu Poirier {
746c04148e7SMathieu Poirier 	int ret;
747c04148e7SMathieu Poirier 	unsigned long val;
748c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
7491925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
750c04148e7SMathieu Poirier 
751c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
752c04148e7SMathieu Poirier 	if (ret)
753c04148e7SMathieu Poirier 		return ret;
754c04148e7SMathieu Poirier 
755c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
7561925a470SMathieu Poirier 	config->cntr_val[config->cntr_idx] = val;
757c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
758c04148e7SMathieu Poirier 
759c04148e7SMathieu Poirier 	return size;
760c04148e7SMathieu Poirier }
761c04148e7SMathieu Poirier static DEVICE_ATTR_RW(cntr_val);
762c04148e7SMathieu Poirier 
seq_12_event_show(struct device * dev,struct device_attribute * attr,char * buf)763c04148e7SMathieu Poirier static ssize_t seq_12_event_show(struct device *dev,
764c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
765c04148e7SMathieu Poirier {
766c04148e7SMathieu Poirier 	unsigned long val;
767c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
7681925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
769c04148e7SMathieu Poirier 
7701925a470SMathieu Poirier 	val = config->seq_12_event;
771c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
772c04148e7SMathieu Poirier }
773c04148e7SMathieu Poirier 
seq_12_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)774c04148e7SMathieu Poirier static ssize_t seq_12_event_store(struct device *dev,
775c04148e7SMathieu Poirier 				  struct device_attribute *attr,
776c04148e7SMathieu Poirier 				  const char *buf, size_t size)
777c04148e7SMathieu Poirier {
778c04148e7SMathieu Poirier 	int ret;
779c04148e7SMathieu Poirier 	unsigned long val;
780c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
7811925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
782c04148e7SMathieu Poirier 
783c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
784c04148e7SMathieu Poirier 	if (ret)
785c04148e7SMathieu Poirier 		return ret;
786c04148e7SMathieu Poirier 
7871925a470SMathieu Poirier 	config->seq_12_event = val & ETM_EVENT_MASK;
788c04148e7SMathieu Poirier 	return size;
789c04148e7SMathieu Poirier }
790c04148e7SMathieu Poirier static DEVICE_ATTR_RW(seq_12_event);
791c04148e7SMathieu Poirier 
seq_21_event_show(struct device * dev,struct device_attribute * attr,char * buf)792c04148e7SMathieu Poirier static ssize_t seq_21_event_show(struct device *dev,
793c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
794c04148e7SMathieu Poirier {
795c04148e7SMathieu Poirier 	unsigned long val;
796c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
7971925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
798c04148e7SMathieu Poirier 
7991925a470SMathieu Poirier 	val = config->seq_21_event;
800c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
801c04148e7SMathieu Poirier }
802c04148e7SMathieu Poirier 
seq_21_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)803c04148e7SMathieu Poirier static ssize_t seq_21_event_store(struct device *dev,
804c04148e7SMathieu Poirier 				  struct device_attribute *attr,
805c04148e7SMathieu Poirier 				  const char *buf, size_t size)
806c04148e7SMathieu Poirier {
807c04148e7SMathieu Poirier 	int ret;
808c04148e7SMathieu Poirier 	unsigned long val;
809c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
8101925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
811c04148e7SMathieu Poirier 
812c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
813c04148e7SMathieu Poirier 	if (ret)
814c04148e7SMathieu Poirier 		return ret;
815c04148e7SMathieu Poirier 
8161925a470SMathieu Poirier 	config->seq_21_event = val & ETM_EVENT_MASK;
817c04148e7SMathieu Poirier 	return size;
818c04148e7SMathieu Poirier }
819c04148e7SMathieu Poirier static DEVICE_ATTR_RW(seq_21_event);
820c04148e7SMathieu Poirier 
seq_23_event_show(struct device * dev,struct device_attribute * attr,char * buf)821c04148e7SMathieu Poirier static ssize_t seq_23_event_show(struct device *dev,
822c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
823c04148e7SMathieu Poirier {
824c04148e7SMathieu Poirier 	unsigned long val;
825c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
8261925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
827c04148e7SMathieu Poirier 
8281925a470SMathieu Poirier 	val = config->seq_23_event;
829c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
830c04148e7SMathieu Poirier }
831c04148e7SMathieu Poirier 
seq_23_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)832c04148e7SMathieu Poirier static ssize_t seq_23_event_store(struct device *dev,
833c04148e7SMathieu Poirier 				  struct device_attribute *attr,
834c04148e7SMathieu Poirier 				  const char *buf, size_t size)
835c04148e7SMathieu Poirier {
836c04148e7SMathieu Poirier 	int ret;
837c04148e7SMathieu Poirier 	unsigned long val;
838c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
8391925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
840c04148e7SMathieu Poirier 
841c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
842c04148e7SMathieu Poirier 	if (ret)
843c04148e7SMathieu Poirier 		return ret;
844c04148e7SMathieu Poirier 
8451925a470SMathieu Poirier 	config->seq_23_event = val & ETM_EVENT_MASK;
846c04148e7SMathieu Poirier 	return size;
847c04148e7SMathieu Poirier }
848c04148e7SMathieu Poirier static DEVICE_ATTR_RW(seq_23_event);
849c04148e7SMathieu Poirier 
seq_31_event_show(struct device * dev,struct device_attribute * attr,char * buf)850c04148e7SMathieu Poirier static ssize_t seq_31_event_show(struct device *dev,
851c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
852c04148e7SMathieu Poirier {
853c04148e7SMathieu Poirier 	unsigned long val;
854c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
8551925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
856c04148e7SMathieu Poirier 
8571925a470SMathieu Poirier 	val = config->seq_31_event;
858c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
859c04148e7SMathieu Poirier }
860c04148e7SMathieu Poirier 
seq_31_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)861c04148e7SMathieu Poirier static ssize_t seq_31_event_store(struct device *dev,
862c04148e7SMathieu Poirier 				  struct device_attribute *attr,
863c04148e7SMathieu Poirier 				  const char *buf, size_t size)
864c04148e7SMathieu Poirier {
865c04148e7SMathieu Poirier 	int ret;
866c04148e7SMathieu Poirier 	unsigned long val;
867c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
8681925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
869c04148e7SMathieu Poirier 
870c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
871c04148e7SMathieu Poirier 	if (ret)
872c04148e7SMathieu Poirier 		return ret;
873c04148e7SMathieu Poirier 
8741925a470SMathieu Poirier 	config->seq_31_event = val & ETM_EVENT_MASK;
875c04148e7SMathieu Poirier 	return size;
876c04148e7SMathieu Poirier }
877c04148e7SMathieu Poirier static DEVICE_ATTR_RW(seq_31_event);
878c04148e7SMathieu Poirier 
seq_32_event_show(struct device * dev,struct device_attribute * attr,char * buf)879c04148e7SMathieu Poirier static ssize_t seq_32_event_show(struct device *dev,
880c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
881c04148e7SMathieu Poirier {
882c04148e7SMathieu Poirier 	unsigned long val;
883c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
8841925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
885c04148e7SMathieu Poirier 
8861925a470SMathieu Poirier 	val = config->seq_32_event;
887c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
888c04148e7SMathieu Poirier }
889c04148e7SMathieu Poirier 
seq_32_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)890c04148e7SMathieu Poirier static ssize_t seq_32_event_store(struct device *dev,
891c04148e7SMathieu Poirier 				  struct device_attribute *attr,
892c04148e7SMathieu Poirier 				  const char *buf, size_t size)
893c04148e7SMathieu Poirier {
894c04148e7SMathieu Poirier 	int ret;
895c04148e7SMathieu Poirier 	unsigned long val;
896c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
8971925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
898c04148e7SMathieu Poirier 
899c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
900c04148e7SMathieu Poirier 	if (ret)
901c04148e7SMathieu Poirier 		return ret;
902c04148e7SMathieu Poirier 
9031925a470SMathieu Poirier 	config->seq_32_event = val & ETM_EVENT_MASK;
904c04148e7SMathieu Poirier 	return size;
905c04148e7SMathieu Poirier }
906c04148e7SMathieu Poirier static DEVICE_ATTR_RW(seq_32_event);
907c04148e7SMathieu Poirier 
seq_13_event_show(struct device * dev,struct device_attribute * attr,char * buf)908c04148e7SMathieu Poirier static ssize_t seq_13_event_show(struct device *dev,
909c04148e7SMathieu Poirier 				 struct device_attribute *attr, char *buf)
910c04148e7SMathieu Poirier {
911c04148e7SMathieu Poirier 	unsigned long val;
912c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
9131925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
914c04148e7SMathieu Poirier 
9151925a470SMathieu Poirier 	val = config->seq_13_event;
916c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
917c04148e7SMathieu Poirier }
918c04148e7SMathieu Poirier 
seq_13_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)919c04148e7SMathieu Poirier static ssize_t seq_13_event_store(struct device *dev,
920c04148e7SMathieu Poirier 				  struct device_attribute *attr,
921c04148e7SMathieu Poirier 				  const char *buf, size_t size)
922c04148e7SMathieu Poirier {
923c04148e7SMathieu Poirier 	int ret;
924c04148e7SMathieu Poirier 	unsigned long val;
925c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
9261925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
927c04148e7SMathieu Poirier 
928c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
929c04148e7SMathieu Poirier 	if (ret)
930c04148e7SMathieu Poirier 		return ret;
931c04148e7SMathieu Poirier 
9321925a470SMathieu Poirier 	config->seq_13_event = val & ETM_EVENT_MASK;
933c04148e7SMathieu Poirier 	return size;
934c04148e7SMathieu Poirier }
935c04148e7SMathieu Poirier static DEVICE_ATTR_RW(seq_13_event);
936c04148e7SMathieu Poirier 
seq_curr_state_show(struct device * dev,struct device_attribute * attr,char * buf)937c04148e7SMathieu Poirier static ssize_t seq_curr_state_show(struct device *dev,
938c04148e7SMathieu Poirier 				   struct device_attribute *attr, char *buf)
939c04148e7SMathieu Poirier {
940c04148e7SMathieu Poirier 	unsigned long val, flags;
941c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
9421925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
943c04148e7SMathieu Poirier 
94422fd532eSMathieu Poirier 	if (!local_read(&drvdata->mode)) {
9451925a470SMathieu Poirier 		val = config->seq_curr_state;
946c04148e7SMathieu Poirier 		goto out;
947c04148e7SMathieu Poirier 	}
948c04148e7SMathieu Poirier 
949aaff7623SSuzuki K Poulose 	pm_runtime_get_sync(dev->parent);
950c04148e7SMathieu Poirier 	spin_lock_irqsave(&drvdata->spinlock, flags);
951c04148e7SMathieu Poirier 
952c04148e7SMathieu Poirier 	CS_UNLOCK(drvdata->base);
953c04148e7SMathieu Poirier 	val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
954c04148e7SMathieu Poirier 	CS_LOCK(drvdata->base);
955c04148e7SMathieu Poirier 
956c04148e7SMathieu Poirier 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
957aaff7623SSuzuki K Poulose 	pm_runtime_put(dev->parent);
958c04148e7SMathieu Poirier out:
959c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
960c04148e7SMathieu Poirier }
961c04148e7SMathieu Poirier 
seq_curr_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)962c04148e7SMathieu Poirier static ssize_t seq_curr_state_store(struct device *dev,
963c04148e7SMathieu Poirier 				    struct device_attribute *attr,
964c04148e7SMathieu Poirier 				    const char *buf, size_t size)
965c04148e7SMathieu Poirier {
966c04148e7SMathieu Poirier 	int ret;
967c04148e7SMathieu Poirier 	unsigned long val;
968c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
9691925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
970c04148e7SMathieu Poirier 
971c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
972c04148e7SMathieu Poirier 	if (ret)
973c04148e7SMathieu Poirier 		return ret;
974c04148e7SMathieu Poirier 
975c04148e7SMathieu Poirier 	if (val > ETM_SEQ_STATE_MAX_VAL)
976c04148e7SMathieu Poirier 		return -EINVAL;
977c04148e7SMathieu Poirier 
9781925a470SMathieu Poirier 	config->seq_curr_state = val;
979c04148e7SMathieu Poirier 
980c04148e7SMathieu Poirier 	return size;
981c04148e7SMathieu Poirier }
982c04148e7SMathieu Poirier static DEVICE_ATTR_RW(seq_curr_state);
983c04148e7SMathieu Poirier 
ctxid_idx_show(struct device * dev,struct device_attribute * attr,char * buf)984c04148e7SMathieu Poirier static ssize_t ctxid_idx_show(struct device *dev,
985c04148e7SMathieu Poirier 			      struct device_attribute *attr, char *buf)
986c04148e7SMathieu Poirier {
987c04148e7SMathieu Poirier 	unsigned long val;
988c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
9891925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
990c04148e7SMathieu Poirier 
9911925a470SMathieu Poirier 	val = config->ctxid_idx;
992c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
993c04148e7SMathieu Poirier }
994c04148e7SMathieu Poirier 
ctxid_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)995c04148e7SMathieu Poirier static ssize_t ctxid_idx_store(struct device *dev,
996c04148e7SMathieu Poirier 				struct device_attribute *attr,
997c04148e7SMathieu Poirier 				const char *buf, size_t size)
998c04148e7SMathieu Poirier {
999c04148e7SMathieu Poirier 	int ret;
1000c04148e7SMathieu Poirier 	unsigned long val;
1001c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
10021925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1003c04148e7SMathieu Poirier 
1004c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
1005c04148e7SMathieu Poirier 	if (ret)
1006c04148e7SMathieu Poirier 		return ret;
1007c04148e7SMathieu Poirier 
1008c04148e7SMathieu Poirier 	if (val >= drvdata->nr_ctxid_cmp)
1009c04148e7SMathieu Poirier 		return -EINVAL;
1010c04148e7SMathieu Poirier 
1011c04148e7SMathieu Poirier 	/*
1012c04148e7SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
1013c04148e7SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
1014c04148e7SMathieu Poirier 	 */
1015c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
10161925a470SMathieu Poirier 	config->ctxid_idx = val;
1017c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1018c04148e7SMathieu Poirier 
1019c04148e7SMathieu Poirier 	return size;
1020c04148e7SMathieu Poirier }
1021c04148e7SMathieu Poirier static DEVICE_ATTR_RW(ctxid_idx);
1022c04148e7SMathieu Poirier 
ctxid_pid_show(struct device * dev,struct device_attribute * attr,char * buf)1023c04148e7SMathieu Poirier static ssize_t ctxid_pid_show(struct device *dev,
1024c04148e7SMathieu Poirier 			      struct device_attribute *attr, char *buf)
1025c04148e7SMathieu Poirier {
1026c04148e7SMathieu Poirier 	unsigned long val;
1027c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
10281925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1029c04148e7SMathieu Poirier 
10307bd50ccfSMathieu Poirier 	/*
10317bd50ccfSMathieu Poirier 	 * Don't use contextID tracing if coming from a PID namespace.  See
10327bd50ccfSMathieu Poirier 	 * comment in ctxid_pid_store().
10337bd50ccfSMathieu Poirier 	 */
10347bd50ccfSMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
10357bd50ccfSMathieu Poirier 		return -EINVAL;
10367bd50ccfSMathieu Poirier 
1037c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
10387bd50ccfSMathieu Poirier 	val = config->ctxid_pid[config->ctxid_idx];
1039c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1040c04148e7SMathieu Poirier 
1041c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
1042c04148e7SMathieu Poirier }
1043c04148e7SMathieu Poirier 
ctxid_pid_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1044c04148e7SMathieu Poirier static ssize_t ctxid_pid_store(struct device *dev,
1045c04148e7SMathieu Poirier 			       struct device_attribute *attr,
1046c04148e7SMathieu Poirier 			       const char *buf, size_t size)
1047c04148e7SMathieu Poirier {
1048c04148e7SMathieu Poirier 	int ret;
10497bd50ccfSMathieu Poirier 	unsigned long pid;
1050c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
10511925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1052c04148e7SMathieu Poirier 
10537bd50ccfSMathieu Poirier 	/*
10547bd50ccfSMathieu Poirier 	 * When contextID tracing is enabled the tracers will insert the
10557bd50ccfSMathieu Poirier 	 * value found in the contextID register in the trace stream.  But if
10567bd50ccfSMathieu Poirier 	 * a process is in a namespace the PID of that process as seen from the
10577bd50ccfSMathieu Poirier 	 * namespace won't be what the kernel sees, something that makes the
10587bd50ccfSMathieu Poirier 	 * feature confusing and can potentially leak kernel only information.
10597bd50ccfSMathieu Poirier 	 * As such refuse to use the feature if @current is not in the initial
10607bd50ccfSMathieu Poirier 	 * PID namespace.
10617bd50ccfSMathieu Poirier 	 */
10627bd50ccfSMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
10637bd50ccfSMathieu Poirier 		return -EINVAL;
10647bd50ccfSMathieu Poirier 
10657bd50ccfSMathieu Poirier 	ret = kstrtoul(buf, 16, &pid);
1066c04148e7SMathieu Poirier 	if (ret)
1067c04148e7SMathieu Poirier 		return ret;
1068c04148e7SMathieu Poirier 
1069c04148e7SMathieu Poirier 	spin_lock(&drvdata->spinlock);
10701925a470SMathieu Poirier 	config->ctxid_pid[config->ctxid_idx] = pid;
1071c04148e7SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1072c04148e7SMathieu Poirier 
1073c04148e7SMathieu Poirier 	return size;
1074c04148e7SMathieu Poirier }
1075c04148e7SMathieu Poirier static DEVICE_ATTR_RW(ctxid_pid);
1076c04148e7SMathieu Poirier 
ctxid_mask_show(struct device * dev,struct device_attribute * attr,char * buf)1077c04148e7SMathieu Poirier static ssize_t ctxid_mask_show(struct device *dev,
1078c04148e7SMathieu Poirier 			       struct device_attribute *attr, char *buf)
1079c04148e7SMathieu Poirier {
1080c04148e7SMathieu Poirier 	unsigned long val;
1081c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
10821925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1083c04148e7SMathieu Poirier 
10847bd50ccfSMathieu Poirier 	/*
10857bd50ccfSMathieu Poirier 	 * Don't use contextID tracing if coming from a PID namespace.  See
10867bd50ccfSMathieu Poirier 	 * comment in ctxid_pid_store().
10877bd50ccfSMathieu Poirier 	 */
10887bd50ccfSMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
10897bd50ccfSMathieu Poirier 		return -EINVAL;
10907bd50ccfSMathieu Poirier 
10911925a470SMathieu Poirier 	val = config->ctxid_mask;
1092c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
1093c04148e7SMathieu Poirier }
1094c04148e7SMathieu Poirier 
ctxid_mask_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1095c04148e7SMathieu Poirier static ssize_t ctxid_mask_store(struct device *dev,
1096c04148e7SMathieu Poirier 				struct device_attribute *attr,
1097c04148e7SMathieu Poirier 				const char *buf, size_t size)
1098c04148e7SMathieu Poirier {
1099c04148e7SMathieu Poirier 	int ret;
1100c04148e7SMathieu Poirier 	unsigned long val;
1101c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
11021925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1103c04148e7SMathieu Poirier 
11047bd50ccfSMathieu Poirier 	/*
11057bd50ccfSMathieu Poirier 	 * Don't use contextID tracing if coming from a PID namespace.  See
11067bd50ccfSMathieu Poirier 	 * comment in ctxid_pid_store().
11077bd50ccfSMathieu Poirier 	 */
11087bd50ccfSMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
11097bd50ccfSMathieu Poirier 		return -EINVAL;
11107bd50ccfSMathieu Poirier 
1111c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
1112c04148e7SMathieu Poirier 	if (ret)
1113c04148e7SMathieu Poirier 		return ret;
1114c04148e7SMathieu Poirier 
11151925a470SMathieu Poirier 	config->ctxid_mask = val;
1116c04148e7SMathieu Poirier 	return size;
1117c04148e7SMathieu Poirier }
1118c04148e7SMathieu Poirier static DEVICE_ATTR_RW(ctxid_mask);
1119c04148e7SMathieu Poirier 
sync_freq_show(struct device * dev,struct device_attribute * attr,char * buf)1120c04148e7SMathieu Poirier static ssize_t sync_freq_show(struct device *dev,
1121c04148e7SMathieu Poirier 			      struct device_attribute *attr, char *buf)
1122c04148e7SMathieu Poirier {
1123c04148e7SMathieu Poirier 	unsigned long val;
1124c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
11251925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1126c04148e7SMathieu Poirier 
11271925a470SMathieu Poirier 	val = config->sync_freq;
1128c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
1129c04148e7SMathieu Poirier }
1130c04148e7SMathieu Poirier 
sync_freq_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1131c04148e7SMathieu Poirier static ssize_t sync_freq_store(struct device *dev,
1132c04148e7SMathieu Poirier 			       struct device_attribute *attr,
1133c04148e7SMathieu Poirier 			       const char *buf, size_t size)
1134c04148e7SMathieu Poirier {
1135c04148e7SMathieu Poirier 	int ret;
1136c04148e7SMathieu Poirier 	unsigned long val;
1137c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
11381925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1139c04148e7SMathieu Poirier 
1140c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
1141c04148e7SMathieu Poirier 	if (ret)
1142c04148e7SMathieu Poirier 		return ret;
1143c04148e7SMathieu Poirier 
11441925a470SMathieu Poirier 	config->sync_freq = val & ETM_SYNC_MASK;
1145c04148e7SMathieu Poirier 	return size;
1146c04148e7SMathieu Poirier }
1147c04148e7SMathieu Poirier static DEVICE_ATTR_RW(sync_freq);
1148c04148e7SMathieu Poirier 
timestamp_event_show(struct device * dev,struct device_attribute * attr,char * buf)1149c04148e7SMathieu Poirier static ssize_t timestamp_event_show(struct device *dev,
1150c04148e7SMathieu Poirier 				    struct device_attribute *attr, char *buf)
1151c04148e7SMathieu Poirier {
1152c04148e7SMathieu Poirier 	unsigned long val;
1153c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
11541925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1155c04148e7SMathieu Poirier 
11561925a470SMathieu Poirier 	val = config->timestamp_event;
1157c04148e7SMathieu Poirier 	return sprintf(buf, "%#lx\n", val);
1158c04148e7SMathieu Poirier }
1159c04148e7SMathieu Poirier 
timestamp_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1160c04148e7SMathieu Poirier static ssize_t timestamp_event_store(struct device *dev,
1161c04148e7SMathieu Poirier 				     struct device_attribute *attr,
1162c04148e7SMathieu Poirier 				     const char *buf, size_t size)
1163c04148e7SMathieu Poirier {
1164c04148e7SMathieu Poirier 	int ret;
1165c04148e7SMathieu Poirier 	unsigned long val;
1166c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
11671925a470SMathieu Poirier 	struct etm_config *config = &drvdata->config;
1168c04148e7SMathieu Poirier 
1169c04148e7SMathieu Poirier 	ret = kstrtoul(buf, 16, &val);
1170c04148e7SMathieu Poirier 	if (ret)
1171c04148e7SMathieu Poirier 		return ret;
1172c04148e7SMathieu Poirier 
11731925a470SMathieu Poirier 	config->timestamp_event = val & ETM_EVENT_MASK;
1174c04148e7SMathieu Poirier 	return size;
1175c04148e7SMathieu Poirier }
1176c04148e7SMathieu Poirier static DEVICE_ATTR_RW(timestamp_event);
1177c04148e7SMathieu Poirier 
cpu_show(struct device * dev,struct device_attribute * attr,char * buf)1178c04148e7SMathieu Poirier static ssize_t cpu_show(struct device *dev,
1179c04148e7SMathieu Poirier 			struct device_attribute *attr, char *buf)
1180c04148e7SMathieu Poirier {
1181c04148e7SMathieu Poirier 	int val;
1182c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1183c04148e7SMathieu Poirier 
1184c04148e7SMathieu Poirier 	val = drvdata->cpu;
1185c04148e7SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
1186c04148e7SMathieu Poirier 
1187c04148e7SMathieu Poirier }
1188c04148e7SMathieu Poirier static DEVICE_ATTR_RO(cpu);
1189c04148e7SMathieu Poirier 
traceid_show(struct device * dev,struct device_attribute * attr,char * buf)1190c04148e7SMathieu Poirier static ssize_t traceid_show(struct device *dev,
1191c04148e7SMathieu Poirier 			    struct device_attribute *attr, char *buf)
1192c04148e7SMathieu Poirier {
1193*9edf2910SMike Leach 	int trace_id;
1194c04148e7SMathieu Poirier 	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1195c04148e7SMathieu Poirier 
1196*9edf2910SMike Leach 	trace_id = etm_read_alloc_trace_id(drvdata);
1197*9edf2910SMike Leach 	if (trace_id < 0)
1198*9edf2910SMike Leach 		return trace_id;
1199c04148e7SMathieu Poirier 
1200*9edf2910SMike Leach 	return sysfs_emit(buf, "%#x\n", trace_id);
1201c04148e7SMathieu Poirier }
1202*9edf2910SMike Leach static DEVICE_ATTR_RO(traceid);
1203c04148e7SMathieu Poirier 
1204c04148e7SMathieu Poirier static struct attribute *coresight_etm_attrs[] = {
1205c04148e7SMathieu Poirier 	&dev_attr_nr_addr_cmp.attr,
1206c04148e7SMathieu Poirier 	&dev_attr_nr_cntr.attr,
1207c04148e7SMathieu Poirier 	&dev_attr_nr_ctxid_cmp.attr,
1208c04148e7SMathieu Poirier 	&dev_attr_etmsr.attr,
1209c04148e7SMathieu Poirier 	&dev_attr_reset.attr,
1210c04148e7SMathieu Poirier 	&dev_attr_mode.attr,
1211c04148e7SMathieu Poirier 	&dev_attr_trigger_event.attr,
1212c04148e7SMathieu Poirier 	&dev_attr_enable_event.attr,
1213c04148e7SMathieu Poirier 	&dev_attr_fifofull_level.attr,
1214c04148e7SMathieu Poirier 	&dev_attr_addr_idx.attr,
1215c04148e7SMathieu Poirier 	&dev_attr_addr_single.attr,
1216c04148e7SMathieu Poirier 	&dev_attr_addr_range.attr,
1217c04148e7SMathieu Poirier 	&dev_attr_addr_start.attr,
1218c04148e7SMathieu Poirier 	&dev_attr_addr_stop.attr,
1219c04148e7SMathieu Poirier 	&dev_attr_addr_acctype.attr,
1220c04148e7SMathieu Poirier 	&dev_attr_cntr_idx.attr,
1221c04148e7SMathieu Poirier 	&dev_attr_cntr_rld_val.attr,
1222c04148e7SMathieu Poirier 	&dev_attr_cntr_event.attr,
1223c04148e7SMathieu Poirier 	&dev_attr_cntr_rld_event.attr,
1224c04148e7SMathieu Poirier 	&dev_attr_cntr_val.attr,
1225c04148e7SMathieu Poirier 	&dev_attr_seq_12_event.attr,
1226c04148e7SMathieu Poirier 	&dev_attr_seq_21_event.attr,
1227c04148e7SMathieu Poirier 	&dev_attr_seq_23_event.attr,
1228c04148e7SMathieu Poirier 	&dev_attr_seq_31_event.attr,
1229c04148e7SMathieu Poirier 	&dev_attr_seq_32_event.attr,
1230c04148e7SMathieu Poirier 	&dev_attr_seq_13_event.attr,
1231c04148e7SMathieu Poirier 	&dev_attr_seq_curr_state.attr,
1232c04148e7SMathieu Poirier 	&dev_attr_ctxid_idx.attr,
1233c04148e7SMathieu Poirier 	&dev_attr_ctxid_pid.attr,
1234c04148e7SMathieu Poirier 	&dev_attr_ctxid_mask.attr,
1235c04148e7SMathieu Poirier 	&dev_attr_sync_freq.attr,
1236c04148e7SMathieu Poirier 	&dev_attr_timestamp_event.attr,
1237c04148e7SMathieu Poirier 	&dev_attr_traceid.attr,
1238c04148e7SMathieu Poirier 	&dev_attr_cpu.attr,
1239c04148e7SMathieu Poirier 	NULL,
1240c04148e7SMathieu Poirier };
1241c04148e7SMathieu Poirier 
1242c04148e7SMathieu Poirier static struct attribute *coresight_etm_mgmt_attrs[] = {
124308e9fa5fSJames Clark 	coresight_simple_reg32(etmccr, ETMCCR),
124408e9fa5fSJames Clark 	coresight_simple_reg32(etmccer, ETMCCER),
124508e9fa5fSJames Clark 	coresight_simple_reg32(etmscr, ETMSCR),
124608e9fa5fSJames Clark 	coresight_simple_reg32(etmidr, ETMIDR),
124708e9fa5fSJames Clark 	coresight_simple_reg32(etmcr, ETMCR),
124808e9fa5fSJames Clark 	coresight_simple_reg32(etmtraceidr, ETMTRACEIDR),
124908e9fa5fSJames Clark 	coresight_simple_reg32(etmteevr, ETMTEEVR),
125008e9fa5fSJames Clark 	coresight_simple_reg32(etmtssvr, ETMTSSCR),
125108e9fa5fSJames Clark 	coresight_simple_reg32(etmtecr1, ETMTECR1),
125208e9fa5fSJames Clark 	coresight_simple_reg32(etmtecr2, ETMTECR2),
1253c04148e7SMathieu Poirier 	NULL,
1254c04148e7SMathieu Poirier };
1255c04148e7SMathieu Poirier 
1256c04148e7SMathieu Poirier static const struct attribute_group coresight_etm_group = {
1257c04148e7SMathieu Poirier 	.attrs = coresight_etm_attrs,
1258c04148e7SMathieu Poirier };
1259c04148e7SMathieu Poirier 
1260c04148e7SMathieu Poirier static const struct attribute_group coresight_etm_mgmt_group = {
1261c04148e7SMathieu Poirier 	.attrs = coresight_etm_mgmt_attrs,
1262c04148e7SMathieu Poirier 	.name = "mgmt",
1263c04148e7SMathieu Poirier };
1264c04148e7SMathieu Poirier 
1265c04148e7SMathieu Poirier const struct attribute_group *coresight_etm_groups[] = {
1266c04148e7SMathieu Poirier 	&coresight_etm_group,
1267c04148e7SMathieu Poirier 	&coresight_etm_mgmt_group,
1268c04148e7SMathieu Poirier 	NULL,
1269c04148e7SMathieu Poirier };
1270