xref: /openbmc/linux/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1ad0dfdfdSMathieu Poirier // SPDX-License-Identifier: GPL-2.0
2a77de263SMathieu Poirier /*
3a77de263SMathieu Poirier  * Copyright(C) 2015 Linaro Limited. All rights reserved.
4a77de263SMathieu Poirier  * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
5a77de263SMathieu Poirier  */
6a77de263SMathieu Poirier 
7450367f0SMathieu Poirier #include <linux/pid_namespace.h>
8a77de263SMathieu Poirier #include <linux/pm_runtime.h>
9a77de263SMathieu Poirier #include <linux/sysfs.h>
10a77de263SMathieu Poirier #include "coresight-etm4x.h"
112b7adc46SMathieu Poirier #include "coresight-priv.h"
12810ac401SMike Leach #include "coresight-syscfg.h"
13a77de263SMathieu Poirier 
etm4_set_mode_exclude(struct etmv4_drvdata * drvdata,bool exclude)14a77de263SMathieu Poirier static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude)
15a77de263SMathieu Poirier {
1654ff892bSMathieu Poirier 	u8 idx;
1754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1854ff892bSMathieu Poirier 
1954ff892bSMathieu Poirier 	idx = config->addr_idx;
20a77de263SMathieu Poirier 
21a77de263SMathieu Poirier 	/*
22a77de263SMathieu Poirier 	 * TRCACATRn.TYPE bit[1:0]: type of comparison
23a77de263SMathieu Poirier 	 * the trace unit performs
24a77de263SMathieu Poirier 	 */
25f5def772SJames Clark 	if (FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]) == TRCACATRn_TYPE_ADDR) {
26a77de263SMathieu Poirier 		if (idx % 2 != 0)
27a77de263SMathieu Poirier 			return -EINVAL;
28a77de263SMathieu Poirier 
29a77de263SMathieu Poirier 		/*
30a77de263SMathieu Poirier 		 * We are performing instruction address comparison. Set the
31a77de263SMathieu Poirier 		 * relevant bit of ViewInst Include/Exclude Control register
32a77de263SMathieu Poirier 		 * for corresponding address comparator pair.
33a77de263SMathieu Poirier 		 */
3454ff892bSMathieu Poirier 		if (config->addr_type[idx] != ETM_ADDR_TYPE_RANGE ||
3554ff892bSMathieu Poirier 		    config->addr_type[idx + 1] != ETM_ADDR_TYPE_RANGE)
36a77de263SMathieu Poirier 			return -EINVAL;
37a77de263SMathieu Poirier 
38a77de263SMathieu Poirier 		if (exclude == true) {
39a77de263SMathieu Poirier 			/*
40a77de263SMathieu Poirier 			 * Set exclude bit and unset the include bit
41a77de263SMathieu Poirier 			 * corresponding to comparator pair
42a77de263SMathieu Poirier 			 */
4354ff892bSMathieu Poirier 			config->viiectlr |= BIT(idx / 2 + 16);
4454ff892bSMathieu Poirier 			config->viiectlr &= ~BIT(idx / 2);
45a77de263SMathieu Poirier 		} else {
46a77de263SMathieu Poirier 			/*
47a77de263SMathieu Poirier 			 * Set include bit and unset exclude bit
48a77de263SMathieu Poirier 			 * corresponding to comparator pair
49a77de263SMathieu Poirier 			 */
5054ff892bSMathieu Poirier 			config->viiectlr |= BIT(idx / 2);
5154ff892bSMathieu Poirier 			config->viiectlr &= ~BIT(idx / 2 + 16);
52a77de263SMathieu Poirier 		}
53a77de263SMathieu Poirier 	}
54a77de263SMathieu Poirier 	return 0;
55a77de263SMathieu Poirier }
56a77de263SMathieu Poirier 
nr_pe_cmp_show(struct device * dev,struct device_attribute * attr,char * buf)57a77de263SMathieu Poirier static ssize_t nr_pe_cmp_show(struct device *dev,
58a77de263SMathieu Poirier 			      struct device_attribute *attr,
59a77de263SMathieu Poirier 			      char *buf)
60a77de263SMathieu Poirier {
61a77de263SMathieu Poirier 	unsigned long val;
62a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
63a77de263SMathieu Poirier 
64a77de263SMathieu Poirier 	val = drvdata->nr_pe_cmp;
65a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
66a77de263SMathieu Poirier }
67a77de263SMathieu Poirier static DEVICE_ATTR_RO(nr_pe_cmp);
68a77de263SMathieu Poirier 
nr_addr_cmp_show(struct device * dev,struct device_attribute * attr,char * buf)69a77de263SMathieu Poirier static ssize_t nr_addr_cmp_show(struct device *dev,
70a77de263SMathieu Poirier 				struct device_attribute *attr,
71a77de263SMathieu Poirier 				char *buf)
72a77de263SMathieu Poirier {
73a77de263SMathieu Poirier 	unsigned long val;
74a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
75a77de263SMathieu Poirier 
76a77de263SMathieu Poirier 	val = drvdata->nr_addr_cmp;
77a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
78a77de263SMathieu Poirier }
79a77de263SMathieu Poirier static DEVICE_ATTR_RO(nr_addr_cmp);
80a77de263SMathieu Poirier 
nr_cntr_show(struct device * dev,struct device_attribute * attr,char * buf)81a77de263SMathieu Poirier static ssize_t nr_cntr_show(struct device *dev,
82a77de263SMathieu Poirier 			    struct device_attribute *attr,
83a77de263SMathieu Poirier 			    char *buf)
84a77de263SMathieu Poirier {
85a77de263SMathieu Poirier 	unsigned long val;
86a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
87a77de263SMathieu Poirier 
88a77de263SMathieu Poirier 	val = drvdata->nr_cntr;
89a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
90a77de263SMathieu Poirier }
91a77de263SMathieu Poirier static DEVICE_ATTR_RO(nr_cntr);
92a77de263SMathieu Poirier 
nr_ext_inp_show(struct device * dev,struct device_attribute * attr,char * buf)93a77de263SMathieu Poirier static ssize_t nr_ext_inp_show(struct device *dev,
94a77de263SMathieu Poirier 			       struct device_attribute *attr,
95a77de263SMathieu Poirier 			       char *buf)
96a77de263SMathieu Poirier {
97a77de263SMathieu Poirier 	unsigned long val;
98a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
99a77de263SMathieu Poirier 
100a77de263SMathieu Poirier 	val = drvdata->nr_ext_inp;
101a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
102a77de263SMathieu Poirier }
103a77de263SMathieu Poirier static DEVICE_ATTR_RO(nr_ext_inp);
104a77de263SMathieu Poirier 
numcidc_show(struct device * dev,struct device_attribute * attr,char * buf)105a77de263SMathieu Poirier static ssize_t numcidc_show(struct device *dev,
106a77de263SMathieu Poirier 			    struct device_attribute *attr,
107a77de263SMathieu Poirier 			    char *buf)
108a77de263SMathieu Poirier {
109a77de263SMathieu Poirier 	unsigned long val;
110a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
111a77de263SMathieu Poirier 
112a77de263SMathieu Poirier 	val = drvdata->numcidc;
113a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
114a77de263SMathieu Poirier }
115a77de263SMathieu Poirier static DEVICE_ATTR_RO(numcidc);
116a77de263SMathieu Poirier 
numvmidc_show(struct device * dev,struct device_attribute * attr,char * buf)117a77de263SMathieu Poirier static ssize_t numvmidc_show(struct device *dev,
118a77de263SMathieu Poirier 			     struct device_attribute *attr,
119a77de263SMathieu Poirier 			     char *buf)
120a77de263SMathieu Poirier {
121a77de263SMathieu Poirier 	unsigned long val;
122a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
123a77de263SMathieu Poirier 
124a77de263SMathieu Poirier 	val = drvdata->numvmidc;
125a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
126a77de263SMathieu Poirier }
127a77de263SMathieu Poirier static DEVICE_ATTR_RO(numvmidc);
128a77de263SMathieu Poirier 
nrseqstate_show(struct device * dev,struct device_attribute * attr,char * buf)129a77de263SMathieu Poirier static ssize_t nrseqstate_show(struct device *dev,
130a77de263SMathieu Poirier 			       struct device_attribute *attr,
131a77de263SMathieu Poirier 			       char *buf)
132a77de263SMathieu Poirier {
133a77de263SMathieu Poirier 	unsigned long val;
134a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
135a77de263SMathieu Poirier 
136a77de263SMathieu Poirier 	val = drvdata->nrseqstate;
137a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
138a77de263SMathieu Poirier }
139a77de263SMathieu Poirier static DEVICE_ATTR_RO(nrseqstate);
140a77de263SMathieu Poirier 
nr_resource_show(struct device * dev,struct device_attribute * attr,char * buf)141a77de263SMathieu Poirier static ssize_t nr_resource_show(struct device *dev,
142a77de263SMathieu Poirier 				struct device_attribute *attr,
143a77de263SMathieu Poirier 				char *buf)
144a77de263SMathieu Poirier {
145a77de263SMathieu Poirier 	unsigned long val;
146a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
147a77de263SMathieu Poirier 
148a77de263SMathieu Poirier 	val = drvdata->nr_resource;
149a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
150a77de263SMathieu Poirier }
151a77de263SMathieu Poirier static DEVICE_ATTR_RO(nr_resource);
152a77de263SMathieu Poirier 
nr_ss_cmp_show(struct device * dev,struct device_attribute * attr,char * buf)153a77de263SMathieu Poirier static ssize_t nr_ss_cmp_show(struct device *dev,
154a77de263SMathieu Poirier 			      struct device_attribute *attr,
155a77de263SMathieu Poirier 			      char *buf)
156a77de263SMathieu Poirier {
157a77de263SMathieu Poirier 	unsigned long val;
158a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
159a77de263SMathieu Poirier 
160a77de263SMathieu Poirier 	val = drvdata->nr_ss_cmp;
161a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
162a77de263SMathieu Poirier }
163a77de263SMathieu Poirier static DEVICE_ATTR_RO(nr_ss_cmp);
164a77de263SMathieu Poirier 
reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)165a77de263SMathieu Poirier static ssize_t reset_store(struct device *dev,
166a77de263SMathieu Poirier 			   struct device_attribute *attr,
167a77de263SMathieu Poirier 			   const char *buf, size_t size)
168a77de263SMathieu Poirier {
169a77de263SMathieu Poirier 	int i;
170a77de263SMathieu Poirier 	unsigned long val;
171a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
17254ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
173a77de263SMathieu Poirier 
174a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
175a77de263SMathieu Poirier 		return -EINVAL;
176a77de263SMathieu Poirier 
177a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
178a77de263SMathieu Poirier 	if (val)
17954ff892bSMathieu Poirier 		config->mode = 0x0;
180a77de263SMathieu Poirier 
181a77de263SMathieu Poirier 	/* Disable data tracing: do not trace load and store data transfers */
18254ff892bSMathieu Poirier 	config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
1831cf50f64SJames Clark 	config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE);
184a77de263SMathieu Poirier 
185a77de263SMathieu Poirier 	/* Disable data value and data address tracing */
18654ff892bSMathieu Poirier 	config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
187a77de263SMathieu Poirier 			   ETM_MODE_DATA_TRACE_VAL);
1881cf50f64SJames Clark 	config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV);
189a77de263SMathieu Poirier 
190a77de263SMathieu Poirier 	/* Disable all events tracing */
19154ff892bSMathieu Poirier 	config->eventctrl0 = 0x0;
19254ff892bSMathieu Poirier 	config->eventctrl1 = 0x0;
193a77de263SMathieu Poirier 
194a77de263SMathieu Poirier 	/* Disable timestamp event */
19554ff892bSMathieu Poirier 	config->ts_ctrl = 0x0;
196a77de263SMathieu Poirier 
197a77de263SMathieu Poirier 	/* Disable stalling */
19854ff892bSMathieu Poirier 	config->stall_ctrl = 0x0;
199a77de263SMathieu Poirier 
200a77de263SMathieu Poirier 	/* Reset trace synchronization period  to 2^8 = 256 bytes*/
201a77de263SMathieu Poirier 	if (drvdata->syncpr == false)
20254ff892bSMathieu Poirier 		config->syncfreq = 0x8;
203a77de263SMathieu Poirier 
204a77de263SMathieu Poirier 	/*
205a77de263SMathieu Poirier 	 * Enable ViewInst to trace everything with start-stop logic in
206a77de263SMathieu Poirier 	 * started state. ARM recommends start-stop logic is set before
207a77de263SMathieu Poirier 	 * each trace run.
208a77de263SMathieu Poirier 	 */
2096ba7f2bcSJames Clark 	config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
2104020fc8dSJonathan Zhou 	if (drvdata->nr_addr_cmp > 0) {
21154ff892bSMathieu Poirier 		config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
212a77de263SMathieu Poirier 		/* SSSTATUS, bit[9] */
2136ba7f2bcSJames Clark 		config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
214a77de263SMathieu Poirier 	}
215a77de263SMathieu Poirier 
216a77de263SMathieu Poirier 	/* No address range filtering for ViewInst */
21754ff892bSMathieu Poirier 	config->viiectlr = 0x0;
218a77de263SMathieu Poirier 
219a77de263SMathieu Poirier 	/* No start-stop filtering for ViewInst */
22054ff892bSMathieu Poirier 	config->vissctlr = 0x0;
2211b6b0e08SMike Leach 	config->vipcssctlr = 0x0;
222a77de263SMathieu Poirier 
223a77de263SMathieu Poirier 	/* Disable seq events */
224a77de263SMathieu Poirier 	for (i = 0; i < drvdata->nrseqstate-1; i++)
22554ff892bSMathieu Poirier 		config->seq_ctrl[i] = 0x0;
22654ff892bSMathieu Poirier 	config->seq_rst = 0x0;
22754ff892bSMathieu Poirier 	config->seq_state = 0x0;
228a77de263SMathieu Poirier 
229a77de263SMathieu Poirier 	/* Disable external input events */
23054ff892bSMathieu Poirier 	config->ext_inp = 0x0;
231a77de263SMathieu Poirier 
23254ff892bSMathieu Poirier 	config->cntr_idx = 0x0;
233a77de263SMathieu Poirier 	for (i = 0; i < drvdata->nr_cntr; i++) {
23454ff892bSMathieu Poirier 		config->cntrldvr[i] = 0x0;
23554ff892bSMathieu Poirier 		config->cntr_ctrl[i] = 0x0;
23654ff892bSMathieu Poirier 		config->cntr_val[i] = 0x0;
237a77de263SMathieu Poirier 	}
238a77de263SMathieu Poirier 
23954ff892bSMathieu Poirier 	config->res_idx = 0x0;
240685d84a7SJonathan Zhou 	for (i = 2; i < 2 * drvdata->nr_resource; i++)
24154ff892bSMathieu Poirier 		config->res_ctrl[i] = 0x0;
242a77de263SMathieu Poirier 
243ebddaad0SMike Leach 	config->ss_idx = 0x0;
244a77de263SMathieu Poirier 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
24554ff892bSMathieu Poirier 		config->ss_ctrl[i] = 0x0;
24654ff892bSMathieu Poirier 		config->ss_pe_cmp[i] = 0x0;
247a77de263SMathieu Poirier 	}
248a77de263SMathieu Poirier 
24954ff892bSMathieu Poirier 	config->addr_idx = 0x0;
250a77de263SMathieu Poirier 	for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
25154ff892bSMathieu Poirier 		config->addr_val[i] = 0x0;
25254ff892bSMathieu Poirier 		config->addr_acc[i] = 0x0;
25354ff892bSMathieu Poirier 		config->addr_type[i] = ETM_ADDR_TYPE_NONE;
254a77de263SMathieu Poirier 	}
255a77de263SMathieu Poirier 
25654ff892bSMathieu Poirier 	config->ctxid_idx = 0x0;
257450367f0SMathieu Poirier 	for (i = 0; i < drvdata->numcidc; i++)
25854ff892bSMathieu Poirier 		config->ctxid_pid[i] = 0x0;
259a77de263SMathieu Poirier 
26054ff892bSMathieu Poirier 	config->ctxid_mask0 = 0x0;
26154ff892bSMathieu Poirier 	config->ctxid_mask1 = 0x0;
262a77de263SMathieu Poirier 
26354ff892bSMathieu Poirier 	config->vmid_idx = 0x0;
264a77de263SMathieu Poirier 	for (i = 0; i < drvdata->numvmidc; i++)
26554ff892bSMathieu Poirier 		config->vmid_val[i] = 0x0;
26654ff892bSMathieu Poirier 	config->vmid_mask0 = 0x0;
26754ff892bSMathieu Poirier 	config->vmid_mask1 = 0x0;
268a77de263SMathieu Poirier 
269a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
27054ff892bSMathieu Poirier 
271df487120SMike Leach 	/* for sysfs - only release trace id when resetting */
272df487120SMike Leach 	etm4_release_trace_id(drvdata);
273df487120SMike Leach 
274810ac401SMike Leach 	cscfg_csdev_reset_feats(to_coresight_device(dev));
275810ac401SMike Leach 
276a77de263SMathieu Poirier 	return size;
277a77de263SMathieu Poirier }
278a77de263SMathieu Poirier static DEVICE_ATTR_WO(reset);
279a77de263SMathieu Poirier 
mode_show(struct device * dev,struct device_attribute * attr,char * buf)280a77de263SMathieu Poirier static ssize_t mode_show(struct device *dev,
281a77de263SMathieu Poirier 			 struct device_attribute *attr,
282a77de263SMathieu Poirier 			 char *buf)
283a77de263SMathieu Poirier {
284a77de263SMathieu Poirier 	unsigned long val;
285a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
28654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
287a77de263SMathieu Poirier 
28854ff892bSMathieu Poirier 	val = config->mode;
289a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
290a77de263SMathieu Poirier }
291a77de263SMathieu Poirier 
mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)292a77de263SMathieu Poirier static ssize_t mode_store(struct device *dev,
293a77de263SMathieu Poirier 			  struct device_attribute *attr,
294a77de263SMathieu Poirier 			  const char *buf, size_t size)
295a77de263SMathieu Poirier {
296a77de263SMathieu Poirier 	unsigned long val, mode;
297a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
29854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
299a77de263SMathieu Poirier 
300a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
301a77de263SMathieu Poirier 		return -EINVAL;
302a77de263SMathieu Poirier 
303a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
30454ff892bSMathieu Poirier 	config->mode = val & ETMv4_MODE_ALL;
305a77de263SMathieu Poirier 
306a77de263SMathieu Poirier 	if (drvdata->instrp0 == true) {
307a77de263SMathieu Poirier 		/* start by clearing instruction P0 field */
3081cf50f64SJames Clark 		config->cfg  &= ~TRCCONFIGR_INSTP0_LOAD_STORE;
30954ff892bSMathieu Poirier 		if (config->mode & ETM_MODE_LOAD)
310a77de263SMathieu Poirier 			/* 0b01 Trace load instructions as P0 instructions */
3111cf50f64SJames Clark 			config->cfg  |= TRCCONFIGR_INSTP0_LOAD;
31254ff892bSMathieu Poirier 		if (config->mode & ETM_MODE_STORE)
313a77de263SMathieu Poirier 			/* 0b10 Trace store instructions as P0 instructions */
3141cf50f64SJames Clark 			config->cfg  |= TRCCONFIGR_INSTP0_STORE;
31554ff892bSMathieu Poirier 		if (config->mode & ETM_MODE_LOAD_STORE)
316a77de263SMathieu Poirier 			/*
317a77de263SMathieu Poirier 			 * 0b11 Trace load and store instructions
318a77de263SMathieu Poirier 			 * as P0 instructions
319a77de263SMathieu Poirier 			 */
3201cf50f64SJames Clark 			config->cfg  |= TRCCONFIGR_INSTP0_LOAD_STORE;
321a77de263SMathieu Poirier 	}
322a77de263SMathieu Poirier 
323a77de263SMathieu Poirier 	/* bit[3], Branch broadcast mode */
32454ff892bSMathieu Poirier 	if ((config->mode & ETM_MODE_BB) && (drvdata->trcbb == true))
3251cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_BB;
326a77de263SMathieu Poirier 	else
3271cf50f64SJames Clark 		config->cfg &= ~TRCCONFIGR_BB;
328a77de263SMathieu Poirier 
329a77de263SMathieu Poirier 	/* bit[4], Cycle counting instruction trace bit */
33054ff892bSMathieu Poirier 	if ((config->mode & ETMv4_MODE_CYCACC) &&
331a77de263SMathieu Poirier 		(drvdata->trccci == true))
3321cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_CCI;
333a77de263SMathieu Poirier 	else
3341cf50f64SJames Clark 		config->cfg &= ~TRCCONFIGR_CCI;
335a77de263SMathieu Poirier 
336a77de263SMathieu Poirier 	/* bit[6], Context ID tracing bit */
33754ff892bSMathieu Poirier 	if ((config->mode & ETMv4_MODE_CTXID) && (drvdata->ctxid_size))
3381cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_CID;
339a77de263SMathieu Poirier 	else
3401cf50f64SJames Clark 		config->cfg &= ~TRCCONFIGR_CID;
341a77de263SMathieu Poirier 
34254ff892bSMathieu Poirier 	if ((config->mode & ETM_MODE_VMID) && (drvdata->vmid_size))
3431cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_VMID;
344a77de263SMathieu Poirier 	else
3451cf50f64SJames Clark 		config->cfg &= ~TRCCONFIGR_VMID;
346a77de263SMathieu Poirier 
347a77de263SMathieu Poirier 	/* bits[10:8], Conditional instruction tracing bit */
34854ff892bSMathieu Poirier 	mode = ETM_MODE_COND(config->mode);
349a77de263SMathieu Poirier 	if (drvdata->trccond == true) {
3501cf50f64SJames Clark 		config->cfg &= ~TRCCONFIGR_COND_MASK;
3511cf50f64SJames Clark 		config->cfg |= mode << __bf_shf(TRCCONFIGR_COND_MASK);
352a77de263SMathieu Poirier 	}
353a77de263SMathieu Poirier 
354a77de263SMathieu Poirier 	/* bit[11], Global timestamp tracing bit */
35554ff892bSMathieu Poirier 	if ((config->mode & ETMv4_MODE_TIMESTAMP) && (drvdata->ts_size))
3561cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_TS;
357a77de263SMathieu Poirier 	else
3581cf50f64SJames Clark 		config->cfg &= ~TRCCONFIGR_TS;
359a77de263SMathieu Poirier 
360a77de263SMathieu Poirier 	/* bit[12], Return stack enable bit */
36154ff892bSMathieu Poirier 	if ((config->mode & ETM_MODE_RETURNSTACK) &&
362a77de263SMathieu Poirier 					(drvdata->retstack == true))
3631cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_RS;
364a77de263SMathieu Poirier 	else
3651cf50f64SJames Clark 		config->cfg &= ~TRCCONFIGR_RS;
366a77de263SMathieu Poirier 
367a77de263SMathieu Poirier 	/* bits[14:13], Q element enable field */
36854ff892bSMathieu Poirier 	mode = ETM_MODE_QELEM(config->mode);
369a77de263SMathieu Poirier 	/* start by clearing QE bits */
3701cf50f64SJames Clark 	config->cfg &= ~(TRCCONFIGR_QE_W_COUNTS | TRCCONFIGR_QE_WO_COUNTS);
371ea75a342SJames Clark 	/*
372ea75a342SJames Clark 	 * if supported, Q elements with instruction counts are enabled.
373ea75a342SJames Clark 	 * Always set the low bit for any requested mode. Valid combos are
374ea75a342SJames Clark 	 * 0b00, 0b01 and 0b11.
375ea75a342SJames Clark 	 */
376ea75a342SJames Clark 	if (mode && drvdata->q_support)
3771cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_QE_W_COUNTS;
378a77de263SMathieu Poirier 	/*
379a77de263SMathieu Poirier 	 * if supported, Q elements with and without instruction
380a77de263SMathieu Poirier 	 * counts are enabled
381a77de263SMathieu Poirier 	 */
382a77de263SMathieu Poirier 	if ((mode & BIT(1)) && (drvdata->q_support & BIT(1)))
3831cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_QE_WO_COUNTS;
384a77de263SMathieu Poirier 
385a77de263SMathieu Poirier 	/* bit[11], AMBA Trace Bus (ATB) trigger enable bit */
38654ff892bSMathieu Poirier 	if ((config->mode & ETM_MODE_ATB_TRIGGER) &&
387a77de263SMathieu Poirier 	    (drvdata->atbtrig == true))
388eeae6dddSJames Clark 		config->eventctrl1 |= TRCEVENTCTL1R_ATB;
389a77de263SMathieu Poirier 	else
390eeae6dddSJames Clark 		config->eventctrl1 &= ~TRCEVENTCTL1R_ATB;
391a77de263SMathieu Poirier 
392a77de263SMathieu Poirier 	/* bit[12], Low-power state behavior override bit */
39354ff892bSMathieu Poirier 	if ((config->mode & ETM_MODE_LPOVERRIDE) &&
394a77de263SMathieu Poirier 	    (drvdata->lpoverride == true))
395eeae6dddSJames Clark 		config->eventctrl1 |= TRCEVENTCTL1R_LPOVERRIDE;
396a77de263SMathieu Poirier 	else
397eeae6dddSJames Clark 		config->eventctrl1 &= ~TRCEVENTCTL1R_LPOVERRIDE;
398a77de263SMathieu Poirier 
399a77de263SMathieu Poirier 	/* bit[8], Instruction stall bit */
400f7289606SSuzuki K Poulose 	if ((config->mode & ETM_MODE_ISTALL_EN) && (drvdata->stallctl == true))
401b5bc16abSJames Clark 		config->stall_ctrl |= TRCSTALLCTLR_ISTALL;
402a77de263SMathieu Poirier 	else
403b5bc16abSJames Clark 		config->stall_ctrl &= ~TRCSTALLCTLR_ISTALL;
404a77de263SMathieu Poirier 
405a77de263SMathieu Poirier 	/* bit[10], Prioritize instruction trace bit */
40654ff892bSMathieu Poirier 	if (config->mode & ETM_MODE_INSTPRIO)
407b5bc16abSJames Clark 		config->stall_ctrl |= TRCSTALLCTLR_INSTPRIORITY;
408a77de263SMathieu Poirier 	else
409b5bc16abSJames Clark 		config->stall_ctrl &= ~TRCSTALLCTLR_INSTPRIORITY;
410a77de263SMathieu Poirier 
411a77de263SMathieu Poirier 	/* bit[13], Trace overflow prevention bit */
41254ff892bSMathieu Poirier 	if ((config->mode & ETM_MODE_NOOVERFLOW) &&
413a77de263SMathieu Poirier 		(drvdata->nooverflow == true))
414b5bc16abSJames Clark 		config->stall_ctrl |= TRCSTALLCTLR_NOOVERFLOW;
415a77de263SMathieu Poirier 	else
416b5bc16abSJames Clark 		config->stall_ctrl &= ~TRCSTALLCTLR_NOOVERFLOW;
417a77de263SMathieu Poirier 
418a77de263SMathieu Poirier 	/* bit[9] Start/stop logic control bit */
41954ff892bSMathieu Poirier 	if (config->mode & ETM_MODE_VIEWINST_STARTSTOP)
4206ba7f2bcSJames Clark 		config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
421a77de263SMathieu Poirier 	else
4226ba7f2bcSJames Clark 		config->vinst_ctrl &= ~TRCVICTLR_SSSTATUS;
423a77de263SMathieu Poirier 
424a77de263SMathieu Poirier 	/* bit[10], Whether a trace unit must trace a Reset exception */
42554ff892bSMathieu Poirier 	if (config->mode & ETM_MODE_TRACE_RESET)
4266ba7f2bcSJames Clark 		config->vinst_ctrl |= TRCVICTLR_TRCRESET;
427a77de263SMathieu Poirier 	else
4286ba7f2bcSJames Clark 		config->vinst_ctrl &= ~TRCVICTLR_TRCRESET;
429a77de263SMathieu Poirier 
430a77de263SMathieu Poirier 	/* bit[11], Whether a trace unit must trace a system error exception */
43154ff892bSMathieu Poirier 	if ((config->mode & ETM_MODE_TRACE_ERR) &&
432a77de263SMathieu Poirier 		(drvdata->trc_error == true))
4336ba7f2bcSJames Clark 		config->vinst_ctrl |= TRCVICTLR_TRCERR;
434a77de263SMathieu Poirier 	else
4356ba7f2bcSJames Clark 		config->vinst_ctrl &= ~TRCVICTLR_TRCERR;
436a77de263SMathieu Poirier 
4374f6fce54SMathieu Poirier 	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
4384f6fce54SMathieu Poirier 		etm4_config_trace_mode(config);
4394f6fce54SMathieu Poirier 
440a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
44154ff892bSMathieu Poirier 
442a77de263SMathieu Poirier 	return size;
443a77de263SMathieu Poirier }
444a77de263SMathieu Poirier static DEVICE_ATTR_RW(mode);
445a77de263SMathieu Poirier 
pe_show(struct device * dev,struct device_attribute * attr,char * buf)446a77de263SMathieu Poirier static ssize_t pe_show(struct device *dev,
447a77de263SMathieu Poirier 		       struct device_attribute *attr,
448a77de263SMathieu Poirier 		       char *buf)
449a77de263SMathieu Poirier {
450a77de263SMathieu Poirier 	unsigned long val;
451a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
45254ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
453a77de263SMathieu Poirier 
45454ff892bSMathieu Poirier 	val = config->pe_sel;
455a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
456a77de263SMathieu Poirier }
457a77de263SMathieu Poirier 
pe_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)458a77de263SMathieu Poirier static ssize_t pe_store(struct device *dev,
459a77de263SMathieu Poirier 			struct device_attribute *attr,
460a77de263SMathieu Poirier 			const char *buf, size_t size)
461a77de263SMathieu Poirier {
462a77de263SMathieu Poirier 	unsigned long val;
463a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
46454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
465a77de263SMathieu Poirier 
466a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
467a77de263SMathieu Poirier 		return -EINVAL;
468a77de263SMathieu Poirier 
469a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
470a77de263SMathieu Poirier 	if (val > drvdata->nr_pe) {
471a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
472a77de263SMathieu Poirier 		return -EINVAL;
473a77de263SMathieu Poirier 	}
474a77de263SMathieu Poirier 
47554ff892bSMathieu Poirier 	config->pe_sel = val;
476a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
477a77de263SMathieu Poirier 	return size;
478a77de263SMathieu Poirier }
479a77de263SMathieu Poirier static DEVICE_ATTR_RW(pe);
480a77de263SMathieu Poirier 
event_show(struct device * dev,struct device_attribute * attr,char * buf)481a77de263SMathieu Poirier static ssize_t event_show(struct device *dev,
482a77de263SMathieu Poirier 			  struct device_attribute *attr,
483a77de263SMathieu Poirier 			  char *buf)
484a77de263SMathieu Poirier {
485a77de263SMathieu Poirier 	unsigned long val;
486a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
48754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
488a77de263SMathieu Poirier 
48954ff892bSMathieu Poirier 	val = config->eventctrl0;
490a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
491a77de263SMathieu Poirier }
492a77de263SMathieu Poirier 
event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)493a77de263SMathieu Poirier static ssize_t event_store(struct device *dev,
494a77de263SMathieu Poirier 			   struct device_attribute *attr,
495a77de263SMathieu Poirier 			   const char *buf, size_t size)
496a77de263SMathieu Poirier {
497a77de263SMathieu Poirier 	unsigned long val;
498a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
49954ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
500a77de263SMathieu Poirier 
501a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
502a77de263SMathieu Poirier 		return -EINVAL;
503a77de263SMathieu Poirier 
504a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
505a77de263SMathieu Poirier 	switch (drvdata->nr_event) {
506a77de263SMathieu Poirier 	case 0x0:
507a77de263SMathieu Poirier 		/* EVENT0, bits[7:0] */
50854ff892bSMathieu Poirier 		config->eventctrl0 = val & 0xFF;
509a77de263SMathieu Poirier 		break;
510a77de263SMathieu Poirier 	case 0x1:
511a77de263SMathieu Poirier 		 /* EVENT1, bits[15:8] */
51254ff892bSMathieu Poirier 		config->eventctrl0 = val & 0xFFFF;
513a77de263SMathieu Poirier 		break;
514a77de263SMathieu Poirier 	case 0x2:
515a77de263SMathieu Poirier 		/* EVENT2, bits[23:16] */
51654ff892bSMathieu Poirier 		config->eventctrl0 = val & 0xFFFFFF;
517a77de263SMathieu Poirier 		break;
518a77de263SMathieu Poirier 	case 0x3:
519a77de263SMathieu Poirier 		/* EVENT3, bits[31:24] */
52054ff892bSMathieu Poirier 		config->eventctrl0 = val;
521a77de263SMathieu Poirier 		break;
522a77de263SMathieu Poirier 	default:
523a77de263SMathieu Poirier 		break;
524a77de263SMathieu Poirier 	}
525a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
526a77de263SMathieu Poirier 	return size;
527a77de263SMathieu Poirier }
528a77de263SMathieu Poirier static DEVICE_ATTR_RW(event);
529a77de263SMathieu Poirier 
event_instren_show(struct device * dev,struct device_attribute * attr,char * buf)530a77de263SMathieu Poirier static ssize_t event_instren_show(struct device *dev,
531a77de263SMathieu Poirier 				  struct device_attribute *attr,
532a77de263SMathieu Poirier 				  char *buf)
533a77de263SMathieu Poirier {
534a77de263SMathieu Poirier 	unsigned long val;
535a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
53654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
537a77de263SMathieu Poirier 
538eeae6dddSJames Clark 	val = FIELD_GET(TRCEVENTCTL1R_INSTEN_MASK, config->eventctrl1);
539a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
540a77de263SMathieu Poirier }
541a77de263SMathieu Poirier 
event_instren_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)542a77de263SMathieu Poirier static ssize_t event_instren_store(struct device *dev,
543a77de263SMathieu Poirier 				   struct device_attribute *attr,
544a77de263SMathieu Poirier 				   const char *buf, size_t size)
545a77de263SMathieu Poirier {
546a77de263SMathieu Poirier 	unsigned long val;
547a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
54854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
549a77de263SMathieu Poirier 
550a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
551a77de263SMathieu Poirier 		return -EINVAL;
552a77de263SMathieu Poirier 
553a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
554a77de263SMathieu Poirier 	/* start by clearing all instruction event enable bits */
555eeae6dddSJames Clark 	config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK;
556a77de263SMathieu Poirier 	switch (drvdata->nr_event) {
557a77de263SMathieu Poirier 	case 0x0:
558a77de263SMathieu Poirier 		/* generate Event element for event 1 */
559eeae6dddSJames Clark 		config->eventctrl1 |= val & TRCEVENTCTL1R_INSTEN_1;
560a77de263SMathieu Poirier 		break;
561a77de263SMathieu Poirier 	case 0x1:
562a77de263SMathieu Poirier 		/* generate Event element for event 1 and 2 */
563eeae6dddSJames Clark 		config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 | TRCEVENTCTL1R_INSTEN_1);
564a77de263SMathieu Poirier 		break;
565a77de263SMathieu Poirier 	case 0x2:
566a77de263SMathieu Poirier 		/* generate Event element for event 1, 2 and 3 */
567eeae6dddSJames Clark 		config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 |
568eeae6dddSJames Clark 					     TRCEVENTCTL1R_INSTEN_1 |
569eeae6dddSJames Clark 					     TRCEVENTCTL1R_INSTEN_2);
570a77de263SMathieu Poirier 		break;
571a77de263SMathieu Poirier 	case 0x3:
572a77de263SMathieu Poirier 		/* generate Event element for all 4 events */
573eeae6dddSJames Clark 		config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 |
574eeae6dddSJames Clark 					     TRCEVENTCTL1R_INSTEN_1 |
575eeae6dddSJames Clark 					     TRCEVENTCTL1R_INSTEN_2 |
576eeae6dddSJames Clark 					     TRCEVENTCTL1R_INSTEN_3);
577a77de263SMathieu Poirier 		break;
578a77de263SMathieu Poirier 	default:
579a77de263SMathieu Poirier 		break;
580a77de263SMathieu Poirier 	}
581a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
582a77de263SMathieu Poirier 	return size;
583a77de263SMathieu Poirier }
584a77de263SMathieu Poirier static DEVICE_ATTR_RW(event_instren);
585a77de263SMathieu Poirier 
event_ts_show(struct device * dev,struct device_attribute * attr,char * buf)586a77de263SMathieu Poirier static ssize_t event_ts_show(struct device *dev,
587a77de263SMathieu Poirier 			     struct device_attribute *attr,
588a77de263SMathieu Poirier 			     char *buf)
589a77de263SMathieu Poirier {
590a77de263SMathieu Poirier 	unsigned long val;
591a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
59254ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
593a77de263SMathieu Poirier 
59454ff892bSMathieu Poirier 	val = config->ts_ctrl;
595a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
596a77de263SMathieu Poirier }
597a77de263SMathieu Poirier 
event_ts_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)598a77de263SMathieu Poirier static ssize_t event_ts_store(struct device *dev,
599a77de263SMathieu Poirier 			      struct device_attribute *attr,
600a77de263SMathieu Poirier 			      const char *buf, size_t size)
601a77de263SMathieu Poirier {
602a77de263SMathieu Poirier 	unsigned long val;
603a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
60454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
605a77de263SMathieu Poirier 
606a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
607a77de263SMathieu Poirier 		return -EINVAL;
608a77de263SMathieu Poirier 	if (!drvdata->ts_size)
609a77de263SMathieu Poirier 		return -EINVAL;
610a77de263SMathieu Poirier 
61154ff892bSMathieu Poirier 	config->ts_ctrl = val & ETMv4_EVENT_MASK;
612a77de263SMathieu Poirier 	return size;
613a77de263SMathieu Poirier }
614a77de263SMathieu Poirier static DEVICE_ATTR_RW(event_ts);
615a77de263SMathieu Poirier 
syncfreq_show(struct device * dev,struct device_attribute * attr,char * buf)616a77de263SMathieu Poirier static ssize_t syncfreq_show(struct device *dev,
617a77de263SMathieu Poirier 			     struct device_attribute *attr,
618a77de263SMathieu Poirier 			     char *buf)
619a77de263SMathieu Poirier {
620a77de263SMathieu Poirier 	unsigned long val;
621a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
62254ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
623a77de263SMathieu Poirier 
62454ff892bSMathieu Poirier 	val = config->syncfreq;
625a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
626a77de263SMathieu Poirier }
627a77de263SMathieu Poirier 
syncfreq_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)628a77de263SMathieu Poirier static ssize_t syncfreq_store(struct device *dev,
629a77de263SMathieu Poirier 			      struct device_attribute *attr,
630a77de263SMathieu Poirier 			      const char *buf, size_t size)
631a77de263SMathieu Poirier {
632a77de263SMathieu Poirier 	unsigned long val;
633a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
63454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
635a77de263SMathieu Poirier 
636a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
637a77de263SMathieu Poirier 		return -EINVAL;
638a77de263SMathieu Poirier 	if (drvdata->syncpr == true)
639a77de263SMathieu Poirier 		return -EINVAL;
640a77de263SMathieu Poirier 
64154ff892bSMathieu Poirier 	config->syncfreq = val & ETMv4_SYNC_MASK;
642a77de263SMathieu Poirier 	return size;
643a77de263SMathieu Poirier }
644a77de263SMathieu Poirier static DEVICE_ATTR_RW(syncfreq);
645a77de263SMathieu Poirier 
cyc_threshold_show(struct device * dev,struct device_attribute * attr,char * buf)646a77de263SMathieu Poirier static ssize_t cyc_threshold_show(struct device *dev,
647a77de263SMathieu Poirier 				  struct device_attribute *attr,
648a77de263SMathieu Poirier 				  char *buf)
649a77de263SMathieu Poirier {
650a77de263SMathieu Poirier 	unsigned long val;
651a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
65254ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
653a77de263SMathieu Poirier 
65454ff892bSMathieu Poirier 	val = config->ccctlr;
655a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
656a77de263SMathieu Poirier }
657a77de263SMathieu Poirier 
cyc_threshold_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)658a77de263SMathieu Poirier static ssize_t cyc_threshold_store(struct device *dev,
659a77de263SMathieu Poirier 				   struct device_attribute *attr,
660a77de263SMathieu Poirier 				   const char *buf, size_t size)
661a77de263SMathieu Poirier {
662a77de263SMathieu Poirier 	unsigned long val;
663a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
66454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
665a77de263SMathieu Poirier 
666a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
667a77de263SMathieu Poirier 		return -EINVAL;
6682fe6899eSMike Leach 
6692fe6899eSMike Leach 	/* mask off max threshold before checking min value */
6702fe6899eSMike Leach 	val &= ETM_CYC_THRESHOLD_MASK;
671a77de263SMathieu Poirier 	if (val < drvdata->ccitmin)
672a77de263SMathieu Poirier 		return -EINVAL;
673a77de263SMathieu Poirier 
6742fe6899eSMike Leach 	config->ccctlr = val;
675a77de263SMathieu Poirier 	return size;
676a77de263SMathieu Poirier }
677a77de263SMathieu Poirier static DEVICE_ATTR_RW(cyc_threshold);
678a77de263SMathieu Poirier 
bb_ctrl_show(struct device * dev,struct device_attribute * attr,char * buf)679a77de263SMathieu Poirier static ssize_t bb_ctrl_show(struct device *dev,
680a77de263SMathieu Poirier 			    struct device_attribute *attr,
681a77de263SMathieu Poirier 			    char *buf)
682a77de263SMathieu Poirier {
683a77de263SMathieu Poirier 	unsigned long val;
684a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
68554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
686a77de263SMathieu Poirier 
68754ff892bSMathieu Poirier 	val = config->bb_ctrl;
688a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
689a77de263SMathieu Poirier }
690a77de263SMathieu Poirier 
bb_ctrl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)691a77de263SMathieu Poirier static ssize_t bb_ctrl_store(struct device *dev,
692a77de263SMathieu Poirier 			     struct device_attribute *attr,
693a77de263SMathieu Poirier 			     const char *buf, size_t size)
694a77de263SMathieu Poirier {
695a77de263SMathieu Poirier 	unsigned long val;
696a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
69754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
698a77de263SMathieu Poirier 
699a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
700a77de263SMathieu Poirier 		return -EINVAL;
701a77de263SMathieu Poirier 	if (drvdata->trcbb == false)
702a77de263SMathieu Poirier 		return -EINVAL;
703a77de263SMathieu Poirier 	if (!drvdata->nr_addr_cmp)
704a77de263SMathieu Poirier 		return -EINVAL;
7052fe6899eSMike Leach 
706a77de263SMathieu Poirier 	/*
7072fe6899eSMike Leach 	 * Bit[8] controls include(1) / exclude(0), bits[0-7] select
7082fe6899eSMike Leach 	 * individual range comparators. If include then at least 1
7092fe6899eSMike Leach 	 * range must be selected.
710a77de263SMathieu Poirier 	 */
71167493ca4SJames Clark 	if ((val & TRCBBCTLR_MODE) && (FIELD_GET(TRCBBCTLR_RANGE_MASK, val) == 0))
712a77de263SMathieu Poirier 		return -EINVAL;
713a77de263SMathieu Poirier 
71467493ca4SJames Clark 	config->bb_ctrl = val & (TRCBBCTLR_MODE | TRCBBCTLR_RANGE_MASK);
715a77de263SMathieu Poirier 	return size;
716a77de263SMathieu Poirier }
717a77de263SMathieu Poirier static DEVICE_ATTR_RW(bb_ctrl);
718a77de263SMathieu Poirier 
event_vinst_show(struct device * dev,struct device_attribute * attr,char * buf)719a77de263SMathieu Poirier static ssize_t event_vinst_show(struct device *dev,
720a77de263SMathieu Poirier 				struct device_attribute *attr,
721a77de263SMathieu Poirier 				char *buf)
722a77de263SMathieu Poirier {
723a77de263SMathieu Poirier 	unsigned long val;
724a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
72554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
726a77de263SMathieu Poirier 
7276ba7f2bcSJames Clark 	val = FIELD_GET(TRCVICTLR_EVENT_MASK, config->vinst_ctrl);
728a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
729a77de263SMathieu Poirier }
730a77de263SMathieu Poirier 
event_vinst_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)731a77de263SMathieu Poirier static ssize_t event_vinst_store(struct device *dev,
732a77de263SMathieu Poirier 				 struct device_attribute *attr,
733a77de263SMathieu Poirier 				 const char *buf, size_t size)
734a77de263SMathieu Poirier {
735a77de263SMathieu Poirier 	unsigned long val;
736a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
73754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
738a77de263SMathieu Poirier 
739a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
740a77de263SMathieu Poirier 		return -EINVAL;
741a77de263SMathieu Poirier 
742a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
7436ba7f2bcSJames Clark 	val &= TRCVICTLR_EVENT_MASK >> __bf_shf(TRCVICTLR_EVENT_MASK);
7446ba7f2bcSJames Clark 	config->vinst_ctrl &= ~TRCVICTLR_EVENT_MASK;
7456ba7f2bcSJames Clark 	config->vinst_ctrl |= FIELD_PREP(TRCVICTLR_EVENT_MASK, val);
746a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
747a77de263SMathieu Poirier 	return size;
748a77de263SMathieu Poirier }
749a77de263SMathieu Poirier static DEVICE_ATTR_RW(event_vinst);
750a77de263SMathieu Poirier 
s_exlevel_vinst_show(struct device * dev,struct device_attribute * attr,char * buf)751a77de263SMathieu Poirier static ssize_t s_exlevel_vinst_show(struct device *dev,
752a77de263SMathieu Poirier 				    struct device_attribute *attr,
753a77de263SMathieu Poirier 				    char *buf)
754a77de263SMathieu Poirier {
755a77de263SMathieu Poirier 	unsigned long val;
756a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
75754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
758a77de263SMathieu Poirier 
7596ba7f2bcSJames Clark 	val = FIELD_GET(TRCVICTLR_EXLEVEL_S_MASK, config->vinst_ctrl);
760a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
761a77de263SMathieu Poirier }
762a77de263SMathieu Poirier 
s_exlevel_vinst_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)763a77de263SMathieu Poirier static ssize_t s_exlevel_vinst_store(struct device *dev,
764a77de263SMathieu Poirier 				     struct device_attribute *attr,
765a77de263SMathieu Poirier 				     const char *buf, size_t size)
766a77de263SMathieu Poirier {
767a77de263SMathieu Poirier 	unsigned long val;
768a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
76954ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
770a77de263SMathieu Poirier 
771a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
772a77de263SMathieu Poirier 		return -EINVAL;
773a77de263SMathieu Poirier 
774a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
775057f2c57SMike Leach 	/* clear all EXLEVEL_S bits  */
7766ba7f2bcSJames Clark 	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_S_MASK;
777a77de263SMathieu Poirier 	/* enable instruction tracing for corresponding exception level */
778a77de263SMathieu Poirier 	val &= drvdata->s_ex_level;
7796ba7f2bcSJames Clark 	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK);
780a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
781a77de263SMathieu Poirier 	return size;
782a77de263SMathieu Poirier }
783a77de263SMathieu Poirier static DEVICE_ATTR_RW(s_exlevel_vinst);
784a77de263SMathieu Poirier 
ns_exlevel_vinst_show(struct device * dev,struct device_attribute * attr,char * buf)785a77de263SMathieu Poirier static ssize_t ns_exlevel_vinst_show(struct device *dev,
786a77de263SMathieu Poirier 				     struct device_attribute *attr,
787a77de263SMathieu Poirier 				     char *buf)
788a77de263SMathieu Poirier {
789a77de263SMathieu Poirier 	unsigned long val;
790a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
79154ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
792a77de263SMathieu Poirier 
793a77de263SMathieu Poirier 	/* EXLEVEL_NS, bits[23:20] */
7946ba7f2bcSJames Clark 	val = FIELD_GET(TRCVICTLR_EXLEVEL_NS_MASK, config->vinst_ctrl);
795a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
796a77de263SMathieu Poirier }
797a77de263SMathieu Poirier 
ns_exlevel_vinst_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)798a77de263SMathieu Poirier static ssize_t ns_exlevel_vinst_store(struct device *dev,
799a77de263SMathieu Poirier 				      struct device_attribute *attr,
800a77de263SMathieu Poirier 				      const char *buf, size_t size)
801a77de263SMathieu Poirier {
802a77de263SMathieu Poirier 	unsigned long val;
803a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
80454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
805a77de263SMathieu Poirier 
806a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
807a77de263SMathieu Poirier 		return -EINVAL;
808a77de263SMathieu Poirier 
809a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
810057f2c57SMike Leach 	/* clear EXLEVEL_NS bits  */
8116ba7f2bcSJames Clark 	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_NS_MASK;
812a77de263SMathieu Poirier 	/* enable instruction tracing for corresponding exception level */
813a77de263SMathieu Poirier 	val &= drvdata->ns_ex_level;
8146ba7f2bcSJames Clark 	config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK);
815a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
816a77de263SMathieu Poirier 	return size;
817a77de263SMathieu Poirier }
818a77de263SMathieu Poirier static DEVICE_ATTR_RW(ns_exlevel_vinst);
819a77de263SMathieu Poirier 
addr_idx_show(struct device * dev,struct device_attribute * attr,char * buf)820a77de263SMathieu Poirier static ssize_t addr_idx_show(struct device *dev,
821a77de263SMathieu Poirier 			     struct device_attribute *attr,
822a77de263SMathieu Poirier 			     char *buf)
823a77de263SMathieu Poirier {
824a77de263SMathieu Poirier 	unsigned long val;
825a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
82654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
827a77de263SMathieu Poirier 
82854ff892bSMathieu Poirier 	val = config->addr_idx;
829a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
830a77de263SMathieu Poirier }
831a77de263SMathieu Poirier 
addr_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)832a77de263SMathieu Poirier static ssize_t addr_idx_store(struct device *dev,
833a77de263SMathieu Poirier 			      struct device_attribute *attr,
834a77de263SMathieu Poirier 			      const char *buf, size_t size)
835a77de263SMathieu Poirier {
836a77de263SMathieu Poirier 	unsigned long val;
837a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
83854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
839a77de263SMathieu Poirier 
840a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
841a77de263SMathieu Poirier 		return -EINVAL;
842a77de263SMathieu Poirier 	if (val >= drvdata->nr_addr_cmp * 2)
843a77de263SMathieu Poirier 		return -EINVAL;
844a77de263SMathieu Poirier 
845a77de263SMathieu Poirier 	/*
846a77de263SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
847a77de263SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
848a77de263SMathieu Poirier 	 */
849a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
85054ff892bSMathieu Poirier 	config->addr_idx = val;
851a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
852a77de263SMathieu Poirier 	return size;
853a77de263SMathieu Poirier }
854a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_idx);
855a77de263SMathieu Poirier 
addr_instdatatype_show(struct device * dev,struct device_attribute * attr,char * buf)856a77de263SMathieu Poirier static ssize_t addr_instdatatype_show(struct device *dev,
857a77de263SMathieu Poirier 				      struct device_attribute *attr,
858a77de263SMathieu Poirier 				      char *buf)
859a77de263SMathieu Poirier {
860a77de263SMathieu Poirier 	ssize_t len;
861a77de263SMathieu Poirier 	u8 val, idx;
862a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
86354ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
864a77de263SMathieu Poirier 
865a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
86654ff892bSMathieu Poirier 	idx = config->addr_idx;
867f5def772SJames Clark 	val = FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]);
868a77de263SMathieu Poirier 	len = scnprintf(buf, PAGE_SIZE, "%s\n",
869f5def772SJames Clark 			val == TRCACATRn_TYPE_ADDR ? "instr" :
870f5def772SJames Clark 			(val == TRCACATRn_TYPE_DATA_LOAD_ADDR ? "data_load" :
871f5def772SJames Clark 			(val == TRCACATRn_TYPE_DATA_STORE_ADDR ? "data_store" :
872a77de263SMathieu Poirier 			"data_load_store")));
873a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
874a77de263SMathieu Poirier 	return len;
875a77de263SMathieu Poirier }
876a77de263SMathieu Poirier 
addr_instdatatype_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)877a77de263SMathieu Poirier static ssize_t addr_instdatatype_store(struct device *dev,
878a77de263SMathieu Poirier 				       struct device_attribute *attr,
879a77de263SMathieu Poirier 				       const char *buf, size_t size)
880a77de263SMathieu Poirier {
881a77de263SMathieu Poirier 	u8 idx;
882a77de263SMathieu Poirier 	char str[20] = "";
883a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
88454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
885a77de263SMathieu Poirier 
886a77de263SMathieu Poirier 	if (strlen(buf) >= 20)
887a77de263SMathieu Poirier 		return -EINVAL;
888a77de263SMathieu Poirier 	if (sscanf(buf, "%s", str) != 1)
889a77de263SMathieu Poirier 		return -EINVAL;
890a77de263SMathieu Poirier 
891a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
89254ff892bSMathieu Poirier 	idx = config->addr_idx;
893a77de263SMathieu Poirier 	if (!strcmp(str, "instr"))
894a77de263SMathieu Poirier 		/* TYPE, bits[1:0] */
895f5def772SJames Clark 		config->addr_acc[idx] &= ~TRCACATRn_TYPE_MASK;
896a77de263SMathieu Poirier 
897a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
898a77de263SMathieu Poirier 	return size;
899a77de263SMathieu Poirier }
900a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_instdatatype);
901a77de263SMathieu Poirier 
addr_single_show(struct device * dev,struct device_attribute * attr,char * buf)902a77de263SMathieu Poirier static ssize_t addr_single_show(struct device *dev,
903a77de263SMathieu Poirier 				struct device_attribute *attr,
904a77de263SMathieu Poirier 				char *buf)
905a77de263SMathieu Poirier {
906a77de263SMathieu Poirier 	u8 idx;
907a77de263SMathieu Poirier 	unsigned long val;
908a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
90954ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
910a77de263SMathieu Poirier 
91154ff892bSMathieu Poirier 	idx = config->addr_idx;
912a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
91354ff892bSMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
91454ff892bSMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
915a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
916a77de263SMathieu Poirier 		return -EPERM;
917a77de263SMathieu Poirier 	}
91854ff892bSMathieu Poirier 	val = (unsigned long)config->addr_val[idx];
919a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
920a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
921a77de263SMathieu Poirier }
922a77de263SMathieu Poirier 
addr_single_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)923a77de263SMathieu Poirier static ssize_t addr_single_store(struct device *dev,
924a77de263SMathieu Poirier 				 struct device_attribute *attr,
925a77de263SMathieu Poirier 				 const char *buf, size_t size)
926a77de263SMathieu Poirier {
927a77de263SMathieu Poirier 	u8 idx;
928a77de263SMathieu Poirier 	unsigned long val;
929a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
93054ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
931a77de263SMathieu Poirier 
932a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
933a77de263SMathieu Poirier 		return -EINVAL;
934a77de263SMathieu Poirier 
935a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
93654ff892bSMathieu Poirier 	idx = config->addr_idx;
93754ff892bSMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
93854ff892bSMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
939a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
940a77de263SMathieu Poirier 		return -EPERM;
941a77de263SMathieu Poirier 	}
942a77de263SMathieu Poirier 
94354ff892bSMathieu Poirier 	config->addr_val[idx] = (u64)val;
94454ff892bSMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
945a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
946a77de263SMathieu Poirier 	return size;
947a77de263SMathieu Poirier }
948a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_single);
949a77de263SMathieu Poirier 
addr_range_show(struct device * dev,struct device_attribute * attr,char * buf)950a77de263SMathieu Poirier static ssize_t addr_range_show(struct device *dev,
951a77de263SMathieu Poirier 			       struct device_attribute *attr,
952a77de263SMathieu Poirier 			       char *buf)
953a77de263SMathieu Poirier {
954a77de263SMathieu Poirier 	u8 idx;
955a77de263SMathieu Poirier 	unsigned long val1, val2;
956a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
95754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
958a77de263SMathieu Poirier 
959a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
96054ff892bSMathieu Poirier 	idx = config->addr_idx;
961a77de263SMathieu Poirier 	if (idx % 2 != 0) {
962a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
963a77de263SMathieu Poirier 		return -EPERM;
964a77de263SMathieu Poirier 	}
96554ff892bSMathieu Poirier 	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
96654ff892bSMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
96754ff892bSMathieu Poirier 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
96854ff892bSMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
969a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
970a77de263SMathieu Poirier 		return -EPERM;
971a77de263SMathieu Poirier 	}
972a77de263SMathieu Poirier 
97354ff892bSMathieu Poirier 	val1 = (unsigned long)config->addr_val[idx];
97454ff892bSMathieu Poirier 	val2 = (unsigned long)config->addr_val[idx + 1];
975a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
976a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
977a77de263SMathieu Poirier }
978a77de263SMathieu Poirier 
addr_range_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)979a77de263SMathieu Poirier static ssize_t addr_range_store(struct device *dev,
980a77de263SMathieu Poirier 				struct device_attribute *attr,
981a77de263SMathieu Poirier 				const char *buf, size_t size)
982a77de263SMathieu Poirier {
983a77de263SMathieu Poirier 	u8 idx;
984a77de263SMathieu Poirier 	unsigned long val1, val2;
985a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
98654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
987c2431fedSMike Leach 	int elements, exclude;
988a77de263SMathieu Poirier 
989c2431fedSMike Leach 	elements = sscanf(buf, "%lx %lx %x", &val1, &val2, &exclude);
990c2431fedSMike Leach 
991c2431fedSMike Leach 	/*  exclude is optional, but need at least two parameter */
992c2431fedSMike Leach 	if (elements < 2)
993a77de263SMathieu Poirier 		return -EINVAL;
994a77de263SMathieu Poirier 	/* lower address comparator cannot have a higher address value */
995a77de263SMathieu Poirier 	if (val1 > val2)
996a77de263SMathieu Poirier 		return -EINVAL;
997a77de263SMathieu Poirier 
998a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
99954ff892bSMathieu Poirier 	idx = config->addr_idx;
1000a77de263SMathieu Poirier 	if (idx % 2 != 0) {
1001a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1002a77de263SMathieu Poirier 		return -EPERM;
1003a77de263SMathieu Poirier 	}
1004a77de263SMathieu Poirier 
100554ff892bSMathieu Poirier 	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
100654ff892bSMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
100754ff892bSMathieu Poirier 	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
100854ff892bSMathieu Poirier 	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
1009a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1010a77de263SMathieu Poirier 		return -EPERM;
1011a77de263SMathieu Poirier 	}
1012a77de263SMathieu Poirier 
101354ff892bSMathieu Poirier 	config->addr_val[idx] = (u64)val1;
101454ff892bSMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
101554ff892bSMathieu Poirier 	config->addr_val[idx + 1] = (u64)val2;
101654ff892bSMathieu Poirier 	config->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
1017a77de263SMathieu Poirier 	/*
1018a77de263SMathieu Poirier 	 * Program include or exclude control bits for vinst or vdata
1019a77de263SMathieu Poirier 	 * whenever we change addr comparators to ETM_ADDR_TYPE_RANGE
1020c2431fedSMike Leach 	 * use supplied value, or default to bit set in 'mode'
1021a77de263SMathieu Poirier 	 */
1022c2431fedSMike Leach 	if (elements != 3)
1023c2431fedSMike Leach 		exclude = config->mode & ETM_MODE_EXCLUDE;
1024c2431fedSMike Leach 	etm4_set_mode_exclude(drvdata, exclude ? true : false);
1025a77de263SMathieu Poirier 
1026a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1027a77de263SMathieu Poirier 	return size;
1028a77de263SMathieu Poirier }
1029a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_range);
1030a77de263SMathieu Poirier 
addr_start_show(struct device * dev,struct device_attribute * attr,char * buf)1031a77de263SMathieu Poirier static ssize_t addr_start_show(struct device *dev,
1032a77de263SMathieu Poirier 			       struct device_attribute *attr,
1033a77de263SMathieu Poirier 			       char *buf)
1034a77de263SMathieu Poirier {
1035a77de263SMathieu Poirier 	u8 idx;
1036a77de263SMathieu Poirier 	unsigned long val;
1037a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
103854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1039a77de263SMathieu Poirier 
1040a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
104154ff892bSMathieu Poirier 	idx = config->addr_idx;
1042a77de263SMathieu Poirier 
104354ff892bSMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
104454ff892bSMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
1045a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1046a77de263SMathieu Poirier 		return -EPERM;
1047a77de263SMathieu Poirier 	}
1048a77de263SMathieu Poirier 
104954ff892bSMathieu Poirier 	val = (unsigned long)config->addr_val[idx];
1050a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1051a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1052a77de263SMathieu Poirier }
1053a77de263SMathieu Poirier 
addr_start_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1054a77de263SMathieu Poirier static ssize_t addr_start_store(struct device *dev,
1055a77de263SMathieu Poirier 				struct device_attribute *attr,
1056a77de263SMathieu Poirier 				const char *buf, size_t size)
1057a77de263SMathieu Poirier {
1058a77de263SMathieu Poirier 	u8 idx;
1059a77de263SMathieu Poirier 	unsigned long val;
1060a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
106154ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1062a77de263SMathieu Poirier 
1063a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1064a77de263SMathieu Poirier 		return -EINVAL;
1065a77de263SMathieu Poirier 
1066a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
106754ff892bSMathieu Poirier 	idx = config->addr_idx;
1068a77de263SMathieu Poirier 	if (!drvdata->nr_addr_cmp) {
1069a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1070a77de263SMathieu Poirier 		return -EINVAL;
1071a77de263SMathieu Poirier 	}
107254ff892bSMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
107354ff892bSMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
1074a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1075a77de263SMathieu Poirier 		return -EPERM;
1076a77de263SMathieu Poirier 	}
1077a77de263SMathieu Poirier 
107854ff892bSMathieu Poirier 	config->addr_val[idx] = (u64)val;
107954ff892bSMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_START;
108054ff892bSMathieu Poirier 	config->vissctlr |= BIT(idx);
1081a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1082a77de263SMathieu Poirier 	return size;
1083a77de263SMathieu Poirier }
1084a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_start);
1085a77de263SMathieu Poirier 
addr_stop_show(struct device * dev,struct device_attribute * attr,char * buf)1086a77de263SMathieu Poirier static ssize_t addr_stop_show(struct device *dev,
1087a77de263SMathieu Poirier 			      struct device_attribute *attr,
1088a77de263SMathieu Poirier 			      char *buf)
1089a77de263SMathieu Poirier {
1090a77de263SMathieu Poirier 	u8 idx;
1091a77de263SMathieu Poirier 	unsigned long val;
1092a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
109354ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1094a77de263SMathieu Poirier 
1095a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
109654ff892bSMathieu Poirier 	idx = config->addr_idx;
1097a77de263SMathieu Poirier 
109854ff892bSMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
109954ff892bSMathieu Poirier 	      config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
1100a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1101a77de263SMathieu Poirier 		return -EPERM;
1102a77de263SMathieu Poirier 	}
1103a77de263SMathieu Poirier 
110454ff892bSMathieu Poirier 	val = (unsigned long)config->addr_val[idx];
1105a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1106a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1107a77de263SMathieu Poirier }
1108a77de263SMathieu Poirier 
addr_stop_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1109a77de263SMathieu Poirier static ssize_t addr_stop_store(struct device *dev,
1110a77de263SMathieu Poirier 			       struct device_attribute *attr,
1111a77de263SMathieu Poirier 			       const char *buf, size_t size)
1112a77de263SMathieu Poirier {
1113a77de263SMathieu Poirier 	u8 idx;
1114a77de263SMathieu Poirier 	unsigned long val;
1115a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
111654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1117a77de263SMathieu Poirier 
1118a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1119a77de263SMathieu Poirier 		return -EINVAL;
1120a77de263SMathieu Poirier 
1121a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
112254ff892bSMathieu Poirier 	idx = config->addr_idx;
1123a77de263SMathieu Poirier 	if (!drvdata->nr_addr_cmp) {
1124a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1125a77de263SMathieu Poirier 		return -EINVAL;
1126a77de263SMathieu Poirier 	}
112754ff892bSMathieu Poirier 	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
112854ff892bSMathieu Poirier 	       config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
1129a77de263SMathieu Poirier 		spin_unlock(&drvdata->spinlock);
1130a77de263SMathieu Poirier 		return -EPERM;
1131a77de263SMathieu Poirier 	}
1132a77de263SMathieu Poirier 
113354ff892bSMathieu Poirier 	config->addr_val[idx] = (u64)val;
113454ff892bSMathieu Poirier 	config->addr_type[idx] = ETM_ADDR_TYPE_STOP;
113554ff892bSMathieu Poirier 	config->vissctlr |= BIT(idx + 16);
1136a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1137a77de263SMathieu Poirier 	return size;
1138a77de263SMathieu Poirier }
1139a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_stop);
1140a77de263SMathieu Poirier 
addr_ctxtype_show(struct device * dev,struct device_attribute * attr,char * buf)1141a77de263SMathieu Poirier static ssize_t addr_ctxtype_show(struct device *dev,
1142a77de263SMathieu Poirier 				 struct device_attribute *attr,
1143a77de263SMathieu Poirier 				 char *buf)
1144a77de263SMathieu Poirier {
1145a77de263SMathieu Poirier 	ssize_t len;
1146a77de263SMathieu Poirier 	u8 idx, val;
1147a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
114854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1149a77de263SMathieu Poirier 
1150a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
115154ff892bSMathieu Poirier 	idx = config->addr_idx;
1152a77de263SMathieu Poirier 	/* CONTEXTTYPE, bits[3:2] */
1153f5def772SJames Clark 	val = FIELD_GET(TRCACATRn_CONTEXTTYPE_MASK, config->addr_acc[idx]);
1154a77de263SMathieu Poirier 	len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
1155a77de263SMathieu Poirier 			(val == ETM_CTX_CTXID ? "ctxid" :
1156a77de263SMathieu Poirier 			(val == ETM_CTX_VMID ? "vmid" : "all")));
1157a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1158a77de263SMathieu Poirier 	return len;
1159a77de263SMathieu Poirier }
1160a77de263SMathieu Poirier 
addr_ctxtype_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1161a77de263SMathieu Poirier static ssize_t addr_ctxtype_store(struct device *dev,
1162a77de263SMathieu Poirier 				  struct device_attribute *attr,
1163a77de263SMathieu Poirier 				  const char *buf, size_t size)
1164a77de263SMathieu Poirier {
1165a77de263SMathieu Poirier 	u8 idx;
1166a77de263SMathieu Poirier 	char str[10] = "";
1167a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
116854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1169a77de263SMathieu Poirier 
1170a77de263SMathieu Poirier 	if (strlen(buf) >= 10)
1171a77de263SMathieu Poirier 		return -EINVAL;
1172a77de263SMathieu Poirier 	if (sscanf(buf, "%s", str) != 1)
1173a77de263SMathieu Poirier 		return -EINVAL;
1174a77de263SMathieu Poirier 
1175a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
117654ff892bSMathieu Poirier 	idx = config->addr_idx;
1177a77de263SMathieu Poirier 	if (!strcmp(str, "none"))
1178a77de263SMathieu Poirier 		/* start by clearing context type bits */
1179f5def772SJames Clark 		config->addr_acc[idx] &= ~TRCACATRn_CONTEXTTYPE_MASK;
1180a77de263SMathieu Poirier 	else if (!strcmp(str, "ctxid")) {
1181a77de263SMathieu Poirier 		/* 0b01 The trace unit performs a Context ID */
1182a77de263SMathieu Poirier 		if (drvdata->numcidc) {
1183f5def772SJames Clark 			config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_CTXID;
1184f5def772SJames Clark 			config->addr_acc[idx] &= ~TRCACATRn_CONTEXTTYPE_VMID;
1185a77de263SMathieu Poirier 		}
1186a77de263SMathieu Poirier 	} else if (!strcmp(str, "vmid")) {
1187a77de263SMathieu Poirier 		/* 0b10 The trace unit performs a VMID */
1188a77de263SMathieu Poirier 		if (drvdata->numvmidc) {
1189f5def772SJames Clark 			config->addr_acc[idx] &= ~TRCACATRn_CONTEXTTYPE_CTXID;
1190f5def772SJames Clark 			config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
1191a77de263SMathieu Poirier 		}
1192a77de263SMathieu Poirier 	} else if (!strcmp(str, "all")) {
1193a77de263SMathieu Poirier 		/*
1194a77de263SMathieu Poirier 		 * 0b11 The trace unit performs a Context ID
1195a77de263SMathieu Poirier 		 * comparison and a VMID
1196a77de263SMathieu Poirier 		 */
1197a77de263SMathieu Poirier 		if (drvdata->numcidc)
1198f5def772SJames Clark 			config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_CTXID;
1199a77de263SMathieu Poirier 		if (drvdata->numvmidc)
1200f5def772SJames Clark 			config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
1201a77de263SMathieu Poirier 	}
1202a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1203a77de263SMathieu Poirier 	return size;
1204a77de263SMathieu Poirier }
1205a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_ctxtype);
1206a77de263SMathieu Poirier 
addr_context_show(struct device * dev,struct device_attribute * attr,char * buf)1207a77de263SMathieu Poirier static ssize_t addr_context_show(struct device *dev,
1208a77de263SMathieu Poirier 				 struct device_attribute *attr,
1209a77de263SMathieu Poirier 				 char *buf)
1210a77de263SMathieu Poirier {
1211a77de263SMathieu Poirier 	u8 idx;
1212a77de263SMathieu Poirier 	unsigned long val;
1213a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
121454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1215a77de263SMathieu Poirier 
1216a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
121754ff892bSMathieu Poirier 	idx = config->addr_idx;
1218a77de263SMathieu Poirier 	/* context ID comparator bits[6:4] */
1219f5def772SJames Clark 	val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]);
1220a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1221a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1222a77de263SMathieu Poirier }
1223a77de263SMathieu Poirier 
addr_context_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1224a77de263SMathieu Poirier static ssize_t addr_context_store(struct device *dev,
1225a77de263SMathieu Poirier 				  struct device_attribute *attr,
1226a77de263SMathieu Poirier 				  const char *buf, size_t size)
1227a77de263SMathieu Poirier {
1228a77de263SMathieu Poirier 	u8 idx;
1229a77de263SMathieu Poirier 	unsigned long val;
1230a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
123154ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1232a77de263SMathieu Poirier 
1233a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1234a77de263SMathieu Poirier 		return -EINVAL;
1235a77de263SMathieu Poirier 	if ((drvdata->numcidc <= 1) && (drvdata->numvmidc <= 1))
1236a77de263SMathieu Poirier 		return -EINVAL;
1237a77de263SMathieu Poirier 	if (val >=  (drvdata->numcidc >= drvdata->numvmidc ?
1238a77de263SMathieu Poirier 		     drvdata->numcidc : drvdata->numvmidc))
1239a77de263SMathieu Poirier 		return -EINVAL;
1240a77de263SMathieu Poirier 
1241a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
124254ff892bSMathieu Poirier 	idx = config->addr_idx;
1243a77de263SMathieu Poirier 	/* clear context ID comparator bits[6:4] */
1244f5def772SJames Clark 	config->addr_acc[idx] &= ~TRCACATRn_CONTEXT_MASK;
1245f5def772SJames Clark 	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_CONTEXT_MASK);
1246a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1247a77de263SMathieu Poirier 	return size;
1248a77de263SMathieu Poirier }
1249a77de263SMathieu Poirier static DEVICE_ATTR_RW(addr_context);
1250a77de263SMathieu Poirier 
addr_exlevel_s_ns_show(struct device * dev,struct device_attribute * attr,char * buf)125175198a7dSMike Leach static ssize_t addr_exlevel_s_ns_show(struct device *dev,
125275198a7dSMike Leach 				      struct device_attribute *attr,
125375198a7dSMike Leach 				      char *buf)
125475198a7dSMike Leach {
125575198a7dSMike Leach 	u8 idx;
125675198a7dSMike Leach 	unsigned long val;
125775198a7dSMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
125875198a7dSMike Leach 	struct etmv4_config *config = &drvdata->config;
125975198a7dSMike Leach 
126075198a7dSMike Leach 	spin_lock(&drvdata->spinlock);
126175198a7dSMike Leach 	idx = config->addr_idx;
1262f5def772SJames Clark 	val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]);
126375198a7dSMike Leach 	spin_unlock(&drvdata->spinlock);
126475198a7dSMike Leach 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
126575198a7dSMike Leach }
126675198a7dSMike Leach 
addr_exlevel_s_ns_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)126775198a7dSMike Leach static ssize_t addr_exlevel_s_ns_store(struct device *dev,
126875198a7dSMike Leach 				       struct device_attribute *attr,
126975198a7dSMike Leach 				       const char *buf, size_t size)
127075198a7dSMike Leach {
127175198a7dSMike Leach 	u8 idx;
127275198a7dSMike Leach 	unsigned long val;
127375198a7dSMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
127475198a7dSMike Leach 	struct etmv4_config *config = &drvdata->config;
127575198a7dSMike Leach 
127675198a7dSMike Leach 	if (kstrtoul(buf, 0, &val))
127775198a7dSMike Leach 		return -EINVAL;
127875198a7dSMike Leach 
1279f5def772SJames Clark 	if (val & ~(TRCACATRn_EXLEVEL_MASK >> __bf_shf(TRCACATRn_EXLEVEL_MASK)))
128075198a7dSMike Leach 		return -EINVAL;
128175198a7dSMike Leach 
128275198a7dSMike Leach 	spin_lock(&drvdata->spinlock);
128375198a7dSMike Leach 	idx = config->addr_idx;
128475198a7dSMike Leach 	/* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */
1285f5def772SJames Clark 	config->addr_acc[idx] &= ~TRCACATRn_EXLEVEL_MASK;
1286f5def772SJames Clark 	config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_EXLEVEL_MASK);
128775198a7dSMike Leach 	spin_unlock(&drvdata->spinlock);
128875198a7dSMike Leach 	return size;
128975198a7dSMike Leach }
129075198a7dSMike Leach static DEVICE_ATTR_RW(addr_exlevel_s_ns);
129175198a7dSMike Leach 
1292a578427dSMike Leach static const char * const addr_type_names[] = {
1293a578427dSMike Leach 	"unused",
1294a578427dSMike Leach 	"single",
1295a578427dSMike Leach 	"range",
1296a578427dSMike Leach 	"start",
1297a578427dSMike Leach 	"stop"
1298a578427dSMike Leach };
1299a578427dSMike Leach 
addr_cmp_view_show(struct device * dev,struct device_attribute * attr,char * buf)1300a578427dSMike Leach static ssize_t addr_cmp_view_show(struct device *dev,
1301a578427dSMike Leach 				  struct device_attribute *attr, char *buf)
1302a578427dSMike Leach {
1303a578427dSMike Leach 	u8 idx, addr_type;
1304a578427dSMike Leach 	unsigned long addr_v, addr_v2, addr_ctrl;
1305a578427dSMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1306a578427dSMike Leach 	struct etmv4_config *config = &drvdata->config;
1307a578427dSMike Leach 	int size = 0;
1308a578427dSMike Leach 	bool exclude = false;
1309a578427dSMike Leach 
1310a578427dSMike Leach 	spin_lock(&drvdata->spinlock);
1311a578427dSMike Leach 	idx = config->addr_idx;
1312a578427dSMike Leach 	addr_v = config->addr_val[idx];
1313a578427dSMike Leach 	addr_ctrl = config->addr_acc[idx];
1314a578427dSMike Leach 	addr_type = config->addr_type[idx];
1315a578427dSMike Leach 	if (addr_type == ETM_ADDR_TYPE_RANGE) {
1316a578427dSMike Leach 		if (idx & 0x1) {
1317a578427dSMike Leach 			idx -= 1;
1318a578427dSMike Leach 			addr_v2 = addr_v;
1319a578427dSMike Leach 			addr_v = config->addr_val[idx];
1320a578427dSMike Leach 		} else {
1321a578427dSMike Leach 			addr_v2 = config->addr_val[idx + 1];
1322a578427dSMike Leach 		}
1323a578427dSMike Leach 		exclude = config->viiectlr & BIT(idx / 2 + 16);
1324a578427dSMike Leach 	}
1325a578427dSMike Leach 	spin_unlock(&drvdata->spinlock);
1326a578427dSMike Leach 	if (addr_type) {
1327a578427dSMike Leach 		size = scnprintf(buf, PAGE_SIZE, "addr_cmp[%i] %s %#lx", idx,
1328a578427dSMike Leach 				 addr_type_names[addr_type], addr_v);
1329a578427dSMike Leach 		if (addr_type == ETM_ADDR_TYPE_RANGE) {
1330a578427dSMike Leach 			size += scnprintf(buf + size, PAGE_SIZE - size,
1331a578427dSMike Leach 					  " %#lx %s", addr_v2,
1332a578427dSMike Leach 					  exclude ? "exclude" : "include");
1333a578427dSMike Leach 		}
1334a578427dSMike Leach 		size += scnprintf(buf + size, PAGE_SIZE - size,
1335a578427dSMike Leach 				  " ctrl(%#lx)\n", addr_ctrl);
1336a578427dSMike Leach 	} else {
1337a578427dSMike Leach 		size = scnprintf(buf, PAGE_SIZE, "addr_cmp[%i] unused\n", idx);
1338a578427dSMike Leach 	}
1339a578427dSMike Leach 	return size;
1340a578427dSMike Leach }
1341a578427dSMike Leach static DEVICE_ATTR_RO(addr_cmp_view);
1342a578427dSMike Leach 
vinst_pe_cmp_start_stop_show(struct device * dev,struct device_attribute * attr,char * buf)13431b6b0e08SMike Leach static ssize_t vinst_pe_cmp_start_stop_show(struct device *dev,
13441b6b0e08SMike Leach 					    struct device_attribute *attr,
13451b6b0e08SMike Leach 					    char *buf)
13461b6b0e08SMike Leach {
13471b6b0e08SMike Leach 	unsigned long val;
13481b6b0e08SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
13491b6b0e08SMike Leach 	struct etmv4_config *config = &drvdata->config;
13501b6b0e08SMike Leach 
13511b6b0e08SMike Leach 	if (!drvdata->nr_pe_cmp)
13521b6b0e08SMike Leach 		return -EINVAL;
13531b6b0e08SMike Leach 	val = config->vipcssctlr;
13541b6b0e08SMike Leach 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
13551b6b0e08SMike Leach }
vinst_pe_cmp_start_stop_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)13561b6b0e08SMike Leach static ssize_t vinst_pe_cmp_start_stop_store(struct device *dev,
13571b6b0e08SMike Leach 					     struct device_attribute *attr,
13581b6b0e08SMike Leach 					     const char *buf, size_t size)
13591b6b0e08SMike Leach {
13601b6b0e08SMike Leach 	unsigned long val;
13611b6b0e08SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
13621b6b0e08SMike Leach 	struct etmv4_config *config = &drvdata->config;
13631b6b0e08SMike Leach 
13641b6b0e08SMike Leach 	if (kstrtoul(buf, 16, &val))
13651b6b0e08SMike Leach 		return -EINVAL;
13661b6b0e08SMike Leach 	if (!drvdata->nr_pe_cmp)
13671b6b0e08SMike Leach 		return -EINVAL;
13681b6b0e08SMike Leach 
13691b6b0e08SMike Leach 	spin_lock(&drvdata->spinlock);
13701b6b0e08SMike Leach 	config->vipcssctlr = val;
13711b6b0e08SMike Leach 	spin_unlock(&drvdata->spinlock);
13721b6b0e08SMike Leach 	return size;
13731b6b0e08SMike Leach }
13741b6b0e08SMike Leach static DEVICE_ATTR_RW(vinst_pe_cmp_start_stop);
13751b6b0e08SMike Leach 
seq_idx_show(struct device * dev,struct device_attribute * attr,char * buf)1376a77de263SMathieu Poirier static ssize_t seq_idx_show(struct device *dev,
1377a77de263SMathieu Poirier 			    struct device_attribute *attr,
1378a77de263SMathieu Poirier 			    char *buf)
1379a77de263SMathieu Poirier {
1380a77de263SMathieu Poirier 	unsigned long val;
1381a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
138254ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1383a77de263SMathieu Poirier 
138454ff892bSMathieu Poirier 	val = config->seq_idx;
1385a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1386a77de263SMathieu Poirier }
1387a77de263SMathieu Poirier 
seq_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1388a77de263SMathieu Poirier static ssize_t seq_idx_store(struct device *dev,
1389a77de263SMathieu Poirier 			     struct device_attribute *attr,
1390a77de263SMathieu Poirier 			     const char *buf, size_t size)
1391a77de263SMathieu Poirier {
1392a77de263SMathieu Poirier 	unsigned long val;
1393a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
139454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1395a77de263SMathieu Poirier 
1396a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1397a77de263SMathieu Poirier 		return -EINVAL;
1398a77de263SMathieu Poirier 	if (val >= drvdata->nrseqstate - 1)
1399a77de263SMathieu Poirier 		return -EINVAL;
1400a77de263SMathieu Poirier 
1401a77de263SMathieu Poirier 	/*
1402a77de263SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
1403a77de263SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
1404a77de263SMathieu Poirier 	 */
1405a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
140654ff892bSMathieu Poirier 	config->seq_idx = val;
1407a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1408a77de263SMathieu Poirier 	return size;
1409a77de263SMathieu Poirier }
1410a77de263SMathieu Poirier static DEVICE_ATTR_RW(seq_idx);
1411a77de263SMathieu Poirier 
seq_state_show(struct device * dev,struct device_attribute * attr,char * buf)1412a77de263SMathieu Poirier static ssize_t seq_state_show(struct device *dev,
1413a77de263SMathieu Poirier 			      struct device_attribute *attr,
1414a77de263SMathieu Poirier 			      char *buf)
1415a77de263SMathieu Poirier {
1416a77de263SMathieu Poirier 	unsigned long val;
1417a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
141854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1419a77de263SMathieu Poirier 
142054ff892bSMathieu Poirier 	val = config->seq_state;
1421a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1422a77de263SMathieu Poirier }
1423a77de263SMathieu Poirier 
seq_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1424a77de263SMathieu Poirier static ssize_t seq_state_store(struct device *dev,
1425a77de263SMathieu Poirier 			       struct device_attribute *attr,
1426a77de263SMathieu Poirier 			       const char *buf, size_t size)
1427a77de263SMathieu Poirier {
1428a77de263SMathieu Poirier 	unsigned long val;
1429a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
143054ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1431a77de263SMathieu Poirier 
1432a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1433a77de263SMathieu Poirier 		return -EINVAL;
1434a77de263SMathieu Poirier 	if (val >= drvdata->nrseqstate)
1435a77de263SMathieu Poirier 		return -EINVAL;
1436a77de263SMathieu Poirier 
143754ff892bSMathieu Poirier 	config->seq_state = val;
1438a77de263SMathieu Poirier 	return size;
1439a77de263SMathieu Poirier }
1440a77de263SMathieu Poirier static DEVICE_ATTR_RW(seq_state);
1441a77de263SMathieu Poirier 
seq_event_show(struct device * dev,struct device_attribute * attr,char * buf)1442a77de263SMathieu Poirier static ssize_t seq_event_show(struct device *dev,
1443a77de263SMathieu Poirier 			      struct device_attribute *attr,
1444a77de263SMathieu Poirier 			      char *buf)
1445a77de263SMathieu Poirier {
1446a77de263SMathieu Poirier 	u8 idx;
1447a77de263SMathieu Poirier 	unsigned long val;
1448a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
144954ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1450a77de263SMathieu Poirier 
1451a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
145254ff892bSMathieu Poirier 	idx = config->seq_idx;
145354ff892bSMathieu Poirier 	val = config->seq_ctrl[idx];
1454a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1455a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1456a77de263SMathieu Poirier }
1457a77de263SMathieu Poirier 
seq_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1458a77de263SMathieu Poirier static ssize_t seq_event_store(struct device *dev,
1459a77de263SMathieu Poirier 			       struct device_attribute *attr,
1460a77de263SMathieu Poirier 			       const char *buf, size_t size)
1461a77de263SMathieu Poirier {
1462a77de263SMathieu Poirier 	u8 idx;
1463a77de263SMathieu Poirier 	unsigned long val;
1464a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
146554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1466a77de263SMathieu Poirier 
1467a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1468a77de263SMathieu Poirier 		return -EINVAL;
1469a77de263SMathieu Poirier 
1470a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
147154ff892bSMathieu Poirier 	idx = config->seq_idx;
14722fe6899eSMike Leach 	/* Seq control has two masks B[15:8] F[7:0] */
14732fe6899eSMike Leach 	config->seq_ctrl[idx] = val & 0xFFFF;
1474a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1475a77de263SMathieu Poirier 	return size;
1476a77de263SMathieu Poirier }
1477a77de263SMathieu Poirier static DEVICE_ATTR_RW(seq_event);
1478a77de263SMathieu Poirier 
seq_reset_event_show(struct device * dev,struct device_attribute * attr,char * buf)1479a77de263SMathieu Poirier static ssize_t seq_reset_event_show(struct device *dev,
1480a77de263SMathieu Poirier 				    struct device_attribute *attr,
1481a77de263SMathieu Poirier 				    char *buf)
1482a77de263SMathieu Poirier {
1483a77de263SMathieu Poirier 	unsigned long val;
1484a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
148554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1486a77de263SMathieu Poirier 
148754ff892bSMathieu Poirier 	val = config->seq_rst;
1488a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1489a77de263SMathieu Poirier }
1490a77de263SMathieu Poirier 
seq_reset_event_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1491a77de263SMathieu Poirier static ssize_t seq_reset_event_store(struct device *dev,
1492a77de263SMathieu Poirier 				     struct device_attribute *attr,
1493a77de263SMathieu Poirier 				     const char *buf, size_t size)
1494a77de263SMathieu Poirier {
1495a77de263SMathieu Poirier 	unsigned long val;
1496a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
149754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1498a77de263SMathieu Poirier 
1499a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1500a77de263SMathieu Poirier 		return -EINVAL;
1501a77de263SMathieu Poirier 	if (!(drvdata->nrseqstate))
1502a77de263SMathieu Poirier 		return -EINVAL;
1503a77de263SMathieu Poirier 
150454ff892bSMathieu Poirier 	config->seq_rst = val & ETMv4_EVENT_MASK;
1505a77de263SMathieu Poirier 	return size;
1506a77de263SMathieu Poirier }
1507a77de263SMathieu Poirier static DEVICE_ATTR_RW(seq_reset_event);
1508a77de263SMathieu Poirier 
cntr_idx_show(struct device * dev,struct device_attribute * attr,char * buf)1509a77de263SMathieu Poirier static ssize_t cntr_idx_show(struct device *dev,
1510a77de263SMathieu Poirier 			     struct device_attribute *attr,
1511a77de263SMathieu Poirier 			     char *buf)
1512a77de263SMathieu Poirier {
1513a77de263SMathieu Poirier 	unsigned long val;
1514a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
151554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1516a77de263SMathieu Poirier 
151754ff892bSMathieu Poirier 	val = config->cntr_idx;
1518a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1519a77de263SMathieu Poirier }
1520a77de263SMathieu Poirier 
cntr_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1521a77de263SMathieu Poirier static ssize_t cntr_idx_store(struct device *dev,
1522a77de263SMathieu Poirier 			      struct device_attribute *attr,
1523a77de263SMathieu Poirier 			      const char *buf, size_t size)
1524a77de263SMathieu Poirier {
1525a77de263SMathieu Poirier 	unsigned long val;
1526a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
152754ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1528a77de263SMathieu Poirier 
1529a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1530a77de263SMathieu Poirier 		return -EINVAL;
1531a77de263SMathieu Poirier 	if (val >= drvdata->nr_cntr)
1532a77de263SMathieu Poirier 		return -EINVAL;
1533a77de263SMathieu Poirier 
1534a77de263SMathieu Poirier 	/*
1535a77de263SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
1536a77de263SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
1537a77de263SMathieu Poirier 	 */
1538a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
153954ff892bSMathieu Poirier 	config->cntr_idx = val;
1540a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1541a77de263SMathieu Poirier 	return size;
1542a77de263SMathieu Poirier }
1543a77de263SMathieu Poirier static DEVICE_ATTR_RW(cntr_idx);
1544a77de263SMathieu Poirier 
cntrldvr_show(struct device * dev,struct device_attribute * attr,char * buf)1545a77de263SMathieu Poirier static ssize_t cntrldvr_show(struct device *dev,
1546a77de263SMathieu Poirier 			     struct device_attribute *attr,
1547a77de263SMathieu Poirier 			     char *buf)
1548a77de263SMathieu Poirier {
1549a77de263SMathieu Poirier 	u8 idx;
1550a77de263SMathieu Poirier 	unsigned long val;
1551a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
155254ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1553a77de263SMathieu Poirier 
1554a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
155554ff892bSMathieu Poirier 	idx = config->cntr_idx;
155654ff892bSMathieu Poirier 	val = config->cntrldvr[idx];
1557a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1558a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1559a77de263SMathieu Poirier }
1560a77de263SMathieu Poirier 
cntrldvr_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1561a77de263SMathieu Poirier static ssize_t cntrldvr_store(struct device *dev,
1562a77de263SMathieu Poirier 			      struct device_attribute *attr,
1563a77de263SMathieu Poirier 			      const char *buf, size_t size)
1564a77de263SMathieu Poirier {
1565a77de263SMathieu Poirier 	u8 idx;
1566a77de263SMathieu Poirier 	unsigned long val;
1567a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
156854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1569a77de263SMathieu Poirier 
1570a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1571a77de263SMathieu Poirier 		return -EINVAL;
1572a77de263SMathieu Poirier 	if (val > ETM_CNTR_MAX_VAL)
1573a77de263SMathieu Poirier 		return -EINVAL;
1574a77de263SMathieu Poirier 
1575a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
157654ff892bSMathieu Poirier 	idx = config->cntr_idx;
157754ff892bSMathieu Poirier 	config->cntrldvr[idx] = val;
1578a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1579a77de263SMathieu Poirier 	return size;
1580a77de263SMathieu Poirier }
1581a77de263SMathieu Poirier static DEVICE_ATTR_RW(cntrldvr);
1582a77de263SMathieu Poirier 
cntr_val_show(struct device * dev,struct device_attribute * attr,char * buf)1583a77de263SMathieu Poirier static ssize_t cntr_val_show(struct device *dev,
1584a77de263SMathieu Poirier 			     struct device_attribute *attr,
1585a77de263SMathieu Poirier 			     char *buf)
1586a77de263SMathieu Poirier {
1587a77de263SMathieu Poirier 	u8 idx;
1588a77de263SMathieu Poirier 	unsigned long val;
1589a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
159054ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1591a77de263SMathieu Poirier 
1592a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
159354ff892bSMathieu Poirier 	idx = config->cntr_idx;
159454ff892bSMathieu Poirier 	val = config->cntr_val[idx];
1595a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1596a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1597a77de263SMathieu Poirier }
1598a77de263SMathieu Poirier 
cntr_val_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1599a77de263SMathieu Poirier static ssize_t cntr_val_store(struct device *dev,
1600a77de263SMathieu Poirier 			      struct device_attribute *attr,
1601a77de263SMathieu Poirier 			      const char *buf, size_t size)
1602a77de263SMathieu Poirier {
1603a77de263SMathieu Poirier 	u8 idx;
1604a77de263SMathieu Poirier 	unsigned long val;
1605a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
160654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1607a77de263SMathieu Poirier 
1608a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1609a77de263SMathieu Poirier 		return -EINVAL;
1610a77de263SMathieu Poirier 	if (val > ETM_CNTR_MAX_VAL)
1611a77de263SMathieu Poirier 		return -EINVAL;
1612a77de263SMathieu Poirier 
1613a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
161454ff892bSMathieu Poirier 	idx = config->cntr_idx;
161554ff892bSMathieu Poirier 	config->cntr_val[idx] = val;
1616a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1617a77de263SMathieu Poirier 	return size;
1618a77de263SMathieu Poirier }
1619a77de263SMathieu Poirier static DEVICE_ATTR_RW(cntr_val);
1620a77de263SMathieu Poirier 
cntr_ctrl_show(struct device * dev,struct device_attribute * attr,char * buf)1621a77de263SMathieu Poirier static ssize_t cntr_ctrl_show(struct device *dev,
1622a77de263SMathieu Poirier 			      struct device_attribute *attr,
1623a77de263SMathieu Poirier 			      char *buf)
1624a77de263SMathieu Poirier {
1625a77de263SMathieu Poirier 	u8 idx;
1626a77de263SMathieu Poirier 	unsigned long val;
1627a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
162854ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1629a77de263SMathieu Poirier 
1630a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
163154ff892bSMathieu Poirier 	idx = config->cntr_idx;
163254ff892bSMathieu Poirier 	val = config->cntr_ctrl[idx];
1633a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1634a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1635a77de263SMathieu Poirier }
1636a77de263SMathieu Poirier 
cntr_ctrl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1637a77de263SMathieu Poirier static ssize_t cntr_ctrl_store(struct device *dev,
1638a77de263SMathieu Poirier 			       struct device_attribute *attr,
1639a77de263SMathieu Poirier 			       const char *buf, size_t size)
1640a77de263SMathieu Poirier {
1641a77de263SMathieu Poirier 	u8 idx;
1642a77de263SMathieu Poirier 	unsigned long val;
1643a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
164454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1645a77de263SMathieu Poirier 
1646a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1647a77de263SMathieu Poirier 		return -EINVAL;
1648a77de263SMathieu Poirier 
1649a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
165054ff892bSMathieu Poirier 	idx = config->cntr_idx;
165154ff892bSMathieu Poirier 	config->cntr_ctrl[idx] = val;
1652a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1653a77de263SMathieu Poirier 	return size;
1654a77de263SMathieu Poirier }
1655a77de263SMathieu Poirier static DEVICE_ATTR_RW(cntr_ctrl);
1656a77de263SMathieu Poirier 
res_idx_show(struct device * dev,struct device_attribute * attr,char * buf)1657a77de263SMathieu Poirier static ssize_t res_idx_show(struct device *dev,
1658a77de263SMathieu Poirier 			    struct device_attribute *attr,
1659a77de263SMathieu Poirier 			    char *buf)
1660a77de263SMathieu Poirier {
1661a77de263SMathieu Poirier 	unsigned long val;
1662a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
166354ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1664a77de263SMathieu Poirier 
166554ff892bSMathieu Poirier 	val = config->res_idx;
1666a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1667a77de263SMathieu Poirier }
1668a77de263SMathieu Poirier 
res_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1669a77de263SMathieu Poirier static ssize_t res_idx_store(struct device *dev,
1670a77de263SMathieu Poirier 			     struct device_attribute *attr,
1671a77de263SMathieu Poirier 			     const char *buf, size_t size)
1672a77de263SMathieu Poirier {
1673a77de263SMathieu Poirier 	unsigned long val;
1674a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
167554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1676a77de263SMathieu Poirier 
1677a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1678a77de263SMathieu Poirier 		return -EINVAL;
1679685d84a7SJonathan Zhou 	/*
1680685d84a7SJonathan Zhou 	 * Resource selector pair 0 is always implemented and reserved,
1681685d84a7SJonathan Zhou 	 * namely an idx with 0 and 1 is illegal.
1682685d84a7SJonathan Zhou 	 */
1683685d84a7SJonathan Zhou 	if ((val < 2) || (val >= 2 * drvdata->nr_resource))
1684a77de263SMathieu Poirier 		return -EINVAL;
1685a77de263SMathieu Poirier 
1686a77de263SMathieu Poirier 	/*
1687a77de263SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
1688a77de263SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
1689a77de263SMathieu Poirier 	 */
1690a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
169154ff892bSMathieu Poirier 	config->res_idx = val;
1692a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1693a77de263SMathieu Poirier 	return size;
1694a77de263SMathieu Poirier }
1695a77de263SMathieu Poirier static DEVICE_ATTR_RW(res_idx);
1696a77de263SMathieu Poirier 
res_ctrl_show(struct device * dev,struct device_attribute * attr,char * buf)1697a77de263SMathieu Poirier static ssize_t res_ctrl_show(struct device *dev,
1698a77de263SMathieu Poirier 			     struct device_attribute *attr,
1699a77de263SMathieu Poirier 			     char *buf)
1700a77de263SMathieu Poirier {
1701a77de263SMathieu Poirier 	u8 idx;
1702a77de263SMathieu Poirier 	unsigned long val;
1703a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
170454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1705a77de263SMathieu Poirier 
1706a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
170754ff892bSMathieu Poirier 	idx = config->res_idx;
170854ff892bSMathieu Poirier 	val = config->res_ctrl[idx];
1709a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1710a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1711a77de263SMathieu Poirier }
1712a77de263SMathieu Poirier 
res_ctrl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1713a77de263SMathieu Poirier static ssize_t res_ctrl_store(struct device *dev,
1714a77de263SMathieu Poirier 			      struct device_attribute *attr,
1715a77de263SMathieu Poirier 			      const char *buf, size_t size)
1716a77de263SMathieu Poirier {
1717a77de263SMathieu Poirier 	u8 idx;
1718a77de263SMathieu Poirier 	unsigned long val;
1719a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
172054ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1721a77de263SMathieu Poirier 
1722a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1723a77de263SMathieu Poirier 		return -EINVAL;
1724a77de263SMathieu Poirier 
1725a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
172654ff892bSMathieu Poirier 	idx = config->res_idx;
1727a77de263SMathieu Poirier 	/* For odd idx pair inversal bit is RES0 */
1728a77de263SMathieu Poirier 	if (idx % 2 != 0)
1729a77de263SMathieu Poirier 		/* PAIRINV, bit[21] */
1730c86dd986SJames Clark 		val &= ~TRCRSCTLRn_PAIRINV;
1731c86dd986SJames Clark 	config->res_ctrl[idx] = val & (TRCRSCTLRn_PAIRINV |
1732c86dd986SJames Clark 				       TRCRSCTLRn_INV |
1733c86dd986SJames Clark 				       TRCRSCTLRn_GROUP_MASK |
1734c86dd986SJames Clark 				       TRCRSCTLRn_SELECT_MASK);
1735a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1736a77de263SMathieu Poirier 	return size;
1737a77de263SMathieu Poirier }
1738a77de263SMathieu Poirier static DEVICE_ATTR_RW(res_ctrl);
1739a77de263SMathieu Poirier 
sshot_idx_show(struct device * dev,struct device_attribute * attr,char * buf)1740ebddaad0SMike Leach static ssize_t sshot_idx_show(struct device *dev,
1741ebddaad0SMike Leach 			      struct device_attribute *attr, char *buf)
1742ebddaad0SMike Leach {
1743ebddaad0SMike Leach 	unsigned long val;
1744ebddaad0SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1745ebddaad0SMike Leach 	struct etmv4_config *config = &drvdata->config;
1746ebddaad0SMike Leach 
1747ebddaad0SMike Leach 	val = config->ss_idx;
1748ebddaad0SMike Leach 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1749ebddaad0SMike Leach }
1750ebddaad0SMike Leach 
sshot_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1751ebddaad0SMike Leach static ssize_t sshot_idx_store(struct device *dev,
1752ebddaad0SMike Leach 			       struct device_attribute *attr,
1753ebddaad0SMike Leach 			       const char *buf, size_t size)
1754ebddaad0SMike Leach {
1755ebddaad0SMike Leach 	unsigned long val;
1756ebddaad0SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1757ebddaad0SMike Leach 	struct etmv4_config *config = &drvdata->config;
1758ebddaad0SMike Leach 
1759ebddaad0SMike Leach 	if (kstrtoul(buf, 16, &val))
1760ebddaad0SMike Leach 		return -EINVAL;
1761ebddaad0SMike Leach 	if (val >= drvdata->nr_ss_cmp)
1762ebddaad0SMike Leach 		return -EINVAL;
1763ebddaad0SMike Leach 
1764ebddaad0SMike Leach 	spin_lock(&drvdata->spinlock);
1765ebddaad0SMike Leach 	config->ss_idx = val;
1766ebddaad0SMike Leach 	spin_unlock(&drvdata->spinlock);
1767ebddaad0SMike Leach 	return size;
1768ebddaad0SMike Leach }
1769ebddaad0SMike Leach static DEVICE_ATTR_RW(sshot_idx);
1770ebddaad0SMike Leach 
sshot_ctrl_show(struct device * dev,struct device_attribute * attr,char * buf)1771ebddaad0SMike Leach static ssize_t sshot_ctrl_show(struct device *dev,
1772ebddaad0SMike Leach 			       struct device_attribute *attr,
1773ebddaad0SMike Leach 			       char *buf)
1774ebddaad0SMike Leach {
1775ebddaad0SMike Leach 	unsigned long val;
1776ebddaad0SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1777ebddaad0SMike Leach 	struct etmv4_config *config = &drvdata->config;
1778ebddaad0SMike Leach 
1779ebddaad0SMike Leach 	spin_lock(&drvdata->spinlock);
1780ebddaad0SMike Leach 	val = config->ss_ctrl[config->ss_idx];
1781ebddaad0SMike Leach 	spin_unlock(&drvdata->spinlock);
1782ebddaad0SMike Leach 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1783ebddaad0SMike Leach }
1784ebddaad0SMike Leach 
sshot_ctrl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1785ebddaad0SMike Leach static ssize_t sshot_ctrl_store(struct device *dev,
1786ebddaad0SMike Leach 				struct device_attribute *attr,
1787ebddaad0SMike Leach 				const char *buf, size_t size)
1788ebddaad0SMike Leach {
1789ebddaad0SMike Leach 	u8 idx;
1790ebddaad0SMike Leach 	unsigned long val;
1791ebddaad0SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1792ebddaad0SMike Leach 	struct etmv4_config *config = &drvdata->config;
1793ebddaad0SMike Leach 
1794ebddaad0SMike Leach 	if (kstrtoul(buf, 16, &val))
1795ebddaad0SMike Leach 		return -EINVAL;
1796ebddaad0SMike Leach 
1797ebddaad0SMike Leach 	spin_lock(&drvdata->spinlock);
1798ebddaad0SMike Leach 	idx = config->ss_idx;
17990544f32bSJames Clark 	config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
1800ebddaad0SMike Leach 	/* must clear bit 31 in related status register on programming */
18010544f32bSJames Clark 	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
1802ebddaad0SMike Leach 	spin_unlock(&drvdata->spinlock);
1803ebddaad0SMike Leach 	return size;
1804ebddaad0SMike Leach }
1805ebddaad0SMike Leach static DEVICE_ATTR_RW(sshot_ctrl);
1806ebddaad0SMike Leach 
sshot_status_show(struct device * dev,struct device_attribute * attr,char * buf)1807ebddaad0SMike Leach static ssize_t sshot_status_show(struct device *dev,
1808ebddaad0SMike Leach 				 struct device_attribute *attr, char *buf)
1809ebddaad0SMike Leach {
1810ebddaad0SMike Leach 	unsigned long val;
1811ebddaad0SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1812ebddaad0SMike Leach 	struct etmv4_config *config = &drvdata->config;
1813ebddaad0SMike Leach 
1814ebddaad0SMike Leach 	spin_lock(&drvdata->spinlock);
1815ebddaad0SMike Leach 	val = config->ss_status[config->ss_idx];
1816ebddaad0SMike Leach 	spin_unlock(&drvdata->spinlock);
1817ebddaad0SMike Leach 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1818ebddaad0SMike Leach }
1819ebddaad0SMike Leach static DEVICE_ATTR_RO(sshot_status);
1820ebddaad0SMike Leach 
sshot_pe_ctrl_show(struct device * dev,struct device_attribute * attr,char * buf)1821ebddaad0SMike Leach static ssize_t sshot_pe_ctrl_show(struct device *dev,
1822ebddaad0SMike Leach 				  struct device_attribute *attr,
1823ebddaad0SMike Leach 				  char *buf)
1824ebddaad0SMike Leach {
1825ebddaad0SMike Leach 	unsigned long val;
1826ebddaad0SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1827ebddaad0SMike Leach 	struct etmv4_config *config = &drvdata->config;
1828ebddaad0SMike Leach 
1829ebddaad0SMike Leach 	spin_lock(&drvdata->spinlock);
1830ebddaad0SMike Leach 	val = config->ss_pe_cmp[config->ss_idx];
1831ebddaad0SMike Leach 	spin_unlock(&drvdata->spinlock);
1832ebddaad0SMike Leach 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1833ebddaad0SMike Leach }
1834ebddaad0SMike Leach 
sshot_pe_ctrl_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1835ebddaad0SMike Leach static ssize_t sshot_pe_ctrl_store(struct device *dev,
1836ebddaad0SMike Leach 				   struct device_attribute *attr,
1837ebddaad0SMike Leach 				   const char *buf, size_t size)
1838ebddaad0SMike Leach {
1839ebddaad0SMike Leach 	u8 idx;
1840ebddaad0SMike Leach 	unsigned long val;
1841ebddaad0SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
1842ebddaad0SMike Leach 	struct etmv4_config *config = &drvdata->config;
1843ebddaad0SMike Leach 
1844ebddaad0SMike Leach 	if (kstrtoul(buf, 16, &val))
1845ebddaad0SMike Leach 		return -EINVAL;
1846ebddaad0SMike Leach 
1847ebddaad0SMike Leach 	spin_lock(&drvdata->spinlock);
1848ebddaad0SMike Leach 	idx = config->ss_idx;
184966192082SJames Clark 	config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
1850ebddaad0SMike Leach 	/* must clear bit 31 in related status register on programming */
18510544f32bSJames Clark 	config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
1852ebddaad0SMike Leach 	spin_unlock(&drvdata->spinlock);
1853ebddaad0SMike Leach 	return size;
1854ebddaad0SMike Leach }
1855ebddaad0SMike Leach static DEVICE_ATTR_RW(sshot_pe_ctrl);
1856ebddaad0SMike Leach 
ctxid_idx_show(struct device * dev,struct device_attribute * attr,char * buf)1857a77de263SMathieu Poirier static ssize_t ctxid_idx_show(struct device *dev,
1858a77de263SMathieu Poirier 			      struct device_attribute *attr,
1859a77de263SMathieu Poirier 			      char *buf)
1860a77de263SMathieu Poirier {
1861a77de263SMathieu Poirier 	unsigned long val;
1862a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
186354ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1864a77de263SMathieu Poirier 
186554ff892bSMathieu Poirier 	val = config->ctxid_idx;
1866a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1867a77de263SMathieu Poirier }
1868a77de263SMathieu Poirier 
ctxid_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1869a77de263SMathieu Poirier static ssize_t ctxid_idx_store(struct device *dev,
1870a77de263SMathieu Poirier 			       struct device_attribute *attr,
1871a77de263SMathieu Poirier 			       const char *buf, size_t size)
1872a77de263SMathieu Poirier {
1873a77de263SMathieu Poirier 	unsigned long val;
1874a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
187554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1876a77de263SMathieu Poirier 
1877a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
1878a77de263SMathieu Poirier 		return -EINVAL;
1879a77de263SMathieu Poirier 	if (val >= drvdata->numcidc)
1880a77de263SMathieu Poirier 		return -EINVAL;
1881a77de263SMathieu Poirier 
1882a77de263SMathieu Poirier 	/*
1883a77de263SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
1884a77de263SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
1885a77de263SMathieu Poirier 	 */
1886a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
188754ff892bSMathieu Poirier 	config->ctxid_idx = val;
1888a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1889a77de263SMathieu Poirier 	return size;
1890a77de263SMathieu Poirier }
1891a77de263SMathieu Poirier static DEVICE_ATTR_RW(ctxid_idx);
1892a77de263SMathieu Poirier 
ctxid_pid_show(struct device * dev,struct device_attribute * attr,char * buf)1893a77de263SMathieu Poirier static ssize_t ctxid_pid_show(struct device *dev,
1894a77de263SMathieu Poirier 			      struct device_attribute *attr,
1895a77de263SMathieu Poirier 			      char *buf)
1896a77de263SMathieu Poirier {
1897a77de263SMathieu Poirier 	u8 idx;
1898a77de263SMathieu Poirier 	unsigned long val;
1899a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
190054ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1901a77de263SMathieu Poirier 
1902450367f0SMathieu Poirier 	/*
1903450367f0SMathieu Poirier 	 * Don't use contextID tracing if coming from a PID namespace.  See
1904450367f0SMathieu Poirier 	 * comment in ctxid_pid_store().
1905450367f0SMathieu Poirier 	 */
1906450367f0SMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
1907450367f0SMathieu Poirier 		return -EINVAL;
1908450367f0SMathieu Poirier 
1909a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
191054ff892bSMathieu Poirier 	idx = config->ctxid_idx;
1911450367f0SMathieu Poirier 	val = (unsigned long)config->ctxid_pid[idx];
1912a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1913a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
1914a77de263SMathieu Poirier }
1915a77de263SMathieu Poirier 
ctxid_pid_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1916a77de263SMathieu Poirier static ssize_t ctxid_pid_store(struct device *dev,
1917a77de263SMathieu Poirier 			       struct device_attribute *attr,
1918a77de263SMathieu Poirier 			       const char *buf, size_t size)
1919a77de263SMathieu Poirier {
1920a77de263SMathieu Poirier 	u8 idx;
1921450367f0SMathieu Poirier 	unsigned long pid;
1922a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
192354ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1924a77de263SMathieu Poirier 
1925a77de263SMathieu Poirier 	/*
1926450367f0SMathieu Poirier 	 * When contextID tracing is enabled the tracers will insert the
1927450367f0SMathieu Poirier 	 * value found in the contextID register in the trace stream.  But if
1928450367f0SMathieu Poirier 	 * a process is in a namespace the PID of that process as seen from the
1929450367f0SMathieu Poirier 	 * namespace won't be what the kernel sees, something that makes the
1930450367f0SMathieu Poirier 	 * feature confusing and can potentially leak kernel only information.
1931450367f0SMathieu Poirier 	 * As such refuse to use the feature if @current is not in the initial
1932450367f0SMathieu Poirier 	 * PID namespace.
1933450367f0SMathieu Poirier 	 */
1934450367f0SMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
1935450367f0SMathieu Poirier 		return -EINVAL;
1936450367f0SMathieu Poirier 
1937450367f0SMathieu Poirier 	/*
1938a77de263SMathieu Poirier 	 * only implemented when ctxid tracing is enabled, i.e. at least one
1939a77de263SMathieu Poirier 	 * ctxid comparator is implemented and ctxid is greater than 0 bits
1940a77de263SMathieu Poirier 	 * in length
1941a77de263SMathieu Poirier 	 */
1942a77de263SMathieu Poirier 	if (!drvdata->ctxid_size || !drvdata->numcidc)
1943a77de263SMathieu Poirier 		return -EINVAL;
1944450367f0SMathieu Poirier 	if (kstrtoul(buf, 16, &pid))
1945a77de263SMathieu Poirier 		return -EINVAL;
1946a77de263SMathieu Poirier 
1947a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
194854ff892bSMathieu Poirier 	idx = config->ctxid_idx;
194954ff892bSMathieu Poirier 	config->ctxid_pid[idx] = (u64)pid;
1950a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1951a77de263SMathieu Poirier 	return size;
1952a77de263SMathieu Poirier }
1953a77de263SMathieu Poirier static DEVICE_ATTR_RW(ctxid_pid);
1954a77de263SMathieu Poirier 
ctxid_masks_show(struct device * dev,struct device_attribute * attr,char * buf)1955a77de263SMathieu Poirier static ssize_t ctxid_masks_show(struct device *dev,
1956a77de263SMathieu Poirier 				struct device_attribute *attr,
1957a77de263SMathieu Poirier 				char *buf)
1958a77de263SMathieu Poirier {
1959a77de263SMathieu Poirier 	unsigned long val1, val2;
1960a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
196154ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
1962a77de263SMathieu Poirier 
1963450367f0SMathieu Poirier 	/*
1964450367f0SMathieu Poirier 	 * Don't use contextID tracing if coming from a PID namespace.  See
1965450367f0SMathieu Poirier 	 * comment in ctxid_pid_store().
1966450367f0SMathieu Poirier 	 */
1967450367f0SMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
1968450367f0SMathieu Poirier 		return -EINVAL;
1969450367f0SMathieu Poirier 
1970a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
197154ff892bSMathieu Poirier 	val1 = config->ctxid_mask0;
197254ff892bSMathieu Poirier 	val2 = config->ctxid_mask1;
1973a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
1974a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
1975a77de263SMathieu Poirier }
1976a77de263SMathieu Poirier 
ctxid_masks_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1977a77de263SMathieu Poirier static ssize_t ctxid_masks_store(struct device *dev,
1978a77de263SMathieu Poirier 				struct device_attribute *attr,
1979a77de263SMathieu Poirier 				const char *buf, size_t size)
1980a77de263SMathieu Poirier {
1981a77de263SMathieu Poirier 	u8 i, j, maskbyte;
1982a77de263SMathieu Poirier 	unsigned long val1, val2, mask;
1983a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
198454ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
19853e12d3b0SMike Leach 	int nr_inputs;
1986a77de263SMathieu Poirier 
1987a77de263SMathieu Poirier 	/*
1988450367f0SMathieu Poirier 	 * Don't use contextID tracing if coming from a PID namespace.  See
1989450367f0SMathieu Poirier 	 * comment in ctxid_pid_store().
1990450367f0SMathieu Poirier 	 */
1991450367f0SMathieu Poirier 	if (task_active_pid_ns(current) != &init_pid_ns)
1992450367f0SMathieu Poirier 		return -EINVAL;
1993450367f0SMathieu Poirier 
1994450367f0SMathieu Poirier 	/*
1995a77de263SMathieu Poirier 	 * only implemented when ctxid tracing is enabled, i.e. at least one
1996a77de263SMathieu Poirier 	 * ctxid comparator is implemented and ctxid is greater than 0 bits
1997a77de263SMathieu Poirier 	 * in length
1998a77de263SMathieu Poirier 	 */
1999a77de263SMathieu Poirier 	if (!drvdata->ctxid_size || !drvdata->numcidc)
2000a77de263SMathieu Poirier 		return -EINVAL;
20013e12d3b0SMike Leach 	/* one mask if <= 4 comparators, two for up to 8 */
20023e12d3b0SMike Leach 	nr_inputs = sscanf(buf, "%lx %lx", &val1, &val2);
20033e12d3b0SMike Leach 	if ((drvdata->numcidc > 4) && (nr_inputs != 2))
2004a77de263SMathieu Poirier 		return -EINVAL;
2005a77de263SMathieu Poirier 
2006a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
2007a77de263SMathieu Poirier 	/*
2008a77de263SMathieu Poirier 	 * each byte[0..3] controls mask value applied to ctxid
2009a77de263SMathieu Poirier 	 * comparator[0..3]
2010a77de263SMathieu Poirier 	 */
2011a77de263SMathieu Poirier 	switch (drvdata->numcidc) {
2012a77de263SMathieu Poirier 	case 0x1:
2013a77de263SMathieu Poirier 		/* COMP0, bits[7:0] */
201454ff892bSMathieu Poirier 		config->ctxid_mask0 = val1 & 0xFF;
2015a77de263SMathieu Poirier 		break;
2016a77de263SMathieu Poirier 	case 0x2:
2017a77de263SMathieu Poirier 		/* COMP1, bits[15:8] */
201854ff892bSMathieu Poirier 		config->ctxid_mask0 = val1 & 0xFFFF;
2019a77de263SMathieu Poirier 		break;
2020a77de263SMathieu Poirier 	case 0x3:
2021a77de263SMathieu Poirier 		/* COMP2, bits[23:16] */
202254ff892bSMathieu Poirier 		config->ctxid_mask0 = val1 & 0xFFFFFF;
2023a77de263SMathieu Poirier 		break;
2024a77de263SMathieu Poirier 	case 0x4:
2025a77de263SMathieu Poirier 		 /* COMP3, bits[31:24] */
202654ff892bSMathieu Poirier 		config->ctxid_mask0 = val1;
2027a77de263SMathieu Poirier 		break;
2028a77de263SMathieu Poirier 	case 0x5:
2029a77de263SMathieu Poirier 		/* COMP4, bits[7:0] */
203054ff892bSMathieu Poirier 		config->ctxid_mask0 = val1;
203154ff892bSMathieu Poirier 		config->ctxid_mask1 = val2 & 0xFF;
2032a77de263SMathieu Poirier 		break;
2033a77de263SMathieu Poirier 	case 0x6:
2034a77de263SMathieu Poirier 		/* COMP5, bits[15:8] */
203554ff892bSMathieu Poirier 		config->ctxid_mask0 = val1;
203654ff892bSMathieu Poirier 		config->ctxid_mask1 = val2 & 0xFFFF;
2037a77de263SMathieu Poirier 		break;
2038a77de263SMathieu Poirier 	case 0x7:
2039a77de263SMathieu Poirier 		/* COMP6, bits[23:16] */
204054ff892bSMathieu Poirier 		config->ctxid_mask0 = val1;
204154ff892bSMathieu Poirier 		config->ctxid_mask1 = val2 & 0xFFFFFF;
2042a77de263SMathieu Poirier 		break;
2043a77de263SMathieu Poirier 	case 0x8:
2044a77de263SMathieu Poirier 		/* COMP7, bits[31:24] */
204554ff892bSMathieu Poirier 		config->ctxid_mask0 = val1;
204654ff892bSMathieu Poirier 		config->ctxid_mask1 = val2;
2047a77de263SMathieu Poirier 		break;
2048a77de263SMathieu Poirier 	default:
2049a77de263SMathieu Poirier 		break;
2050a77de263SMathieu Poirier 	}
2051a77de263SMathieu Poirier 	/*
2052a77de263SMathieu Poirier 	 * If software sets a mask bit to 1, it must program relevant byte
2053a77de263SMathieu Poirier 	 * of ctxid comparator value 0x0, otherwise behavior is unpredictable.
2054a77de263SMathieu Poirier 	 * For example, if bit[3] of ctxid_mask0 is 1, we must clear bits[31:24]
2055a77de263SMathieu Poirier 	 * of ctxid comparator0 value (corresponding to byte 0) register.
2056a77de263SMathieu Poirier 	 */
205754ff892bSMathieu Poirier 	mask = config->ctxid_mask0;
2058a77de263SMathieu Poirier 	for (i = 0; i < drvdata->numcidc; i++) {
2059a77de263SMathieu Poirier 		/* mask value of corresponding ctxid comparator */
2060a77de263SMathieu Poirier 		maskbyte = mask & ETMv4_EVENT_MASK;
2061a77de263SMathieu Poirier 		/*
2062a77de263SMathieu Poirier 		 * each bit corresponds to a byte of respective ctxid comparator
2063a77de263SMathieu Poirier 		 * value register
2064a77de263SMathieu Poirier 		 */
2065a77de263SMathieu Poirier 		for (j = 0; j < 8; j++) {
2066a77de263SMathieu Poirier 			if (maskbyte & 1)
206757adbeeaSBo Yan 				config->ctxid_pid[i] &= ~(0xFFUL << (j * 8));
2068a77de263SMathieu Poirier 			maskbyte >>= 1;
2069a77de263SMathieu Poirier 		}
2070a77de263SMathieu Poirier 		/* Select the next ctxid comparator mask value */
2071a77de263SMathieu Poirier 		if (i == 3)
2072a77de263SMathieu Poirier 			/* ctxid comparators[4-7] */
207354ff892bSMathieu Poirier 			mask = config->ctxid_mask1;
2074a77de263SMathieu Poirier 		else
2075a77de263SMathieu Poirier 			mask >>= 0x8;
2076a77de263SMathieu Poirier 	}
2077a77de263SMathieu Poirier 
2078a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
2079a77de263SMathieu Poirier 	return size;
2080a77de263SMathieu Poirier }
2081a77de263SMathieu Poirier static DEVICE_ATTR_RW(ctxid_masks);
2082a77de263SMathieu Poirier 
vmid_idx_show(struct device * dev,struct device_attribute * attr,char * buf)2083a77de263SMathieu Poirier static ssize_t vmid_idx_show(struct device *dev,
2084a77de263SMathieu Poirier 			     struct device_attribute *attr,
2085a77de263SMathieu Poirier 			     char *buf)
2086a77de263SMathieu Poirier {
2087a77de263SMathieu Poirier 	unsigned long val;
2088a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
208954ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
2090a77de263SMathieu Poirier 
209154ff892bSMathieu Poirier 	val = config->vmid_idx;
2092a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
2093a77de263SMathieu Poirier }
2094a77de263SMathieu Poirier 
vmid_idx_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)2095a77de263SMathieu Poirier static ssize_t vmid_idx_store(struct device *dev,
2096a77de263SMathieu Poirier 			      struct device_attribute *attr,
2097a77de263SMathieu Poirier 			      const char *buf, size_t size)
2098a77de263SMathieu Poirier {
2099a77de263SMathieu Poirier 	unsigned long val;
2100a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
210154ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
2102a77de263SMathieu Poirier 
2103a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
2104a77de263SMathieu Poirier 		return -EINVAL;
2105a77de263SMathieu Poirier 	if (val >= drvdata->numvmidc)
2106a77de263SMathieu Poirier 		return -EINVAL;
2107a77de263SMathieu Poirier 
2108a77de263SMathieu Poirier 	/*
2109a77de263SMathieu Poirier 	 * Use spinlock to ensure index doesn't change while it gets
2110a77de263SMathieu Poirier 	 * dereferenced multiple times within a spinlock block elsewhere.
2111a77de263SMathieu Poirier 	 */
2112a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
211354ff892bSMathieu Poirier 	config->vmid_idx = val;
2114a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
2115a77de263SMathieu Poirier 	return size;
2116a77de263SMathieu Poirier }
2117a77de263SMathieu Poirier static DEVICE_ATTR_RW(vmid_idx);
2118a77de263SMathieu Poirier 
vmid_val_show(struct device * dev,struct device_attribute * attr,char * buf)2119a77de263SMathieu Poirier static ssize_t vmid_val_show(struct device *dev,
2120a77de263SMathieu Poirier 			     struct device_attribute *attr,
2121a77de263SMathieu Poirier 			     char *buf)
2122a77de263SMathieu Poirier {
2123a77de263SMathieu Poirier 	unsigned long val;
2124a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
212554ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
2126a77de263SMathieu Poirier 
21271314dd19SLeo Yan 	/*
21281314dd19SLeo Yan 	 * Don't use virtual contextID tracing if coming from a PID namespace.
21291314dd19SLeo Yan 	 * See comment in ctxid_pid_store().
21301314dd19SLeo Yan 	 */
21311314dd19SLeo Yan 	if (!task_is_in_init_pid_ns(current))
21321314dd19SLeo Yan 		return -EINVAL;
21331314dd19SLeo Yan 
2134bf0ef4f1SLeo Yan 	spin_lock(&drvdata->spinlock);
213554ff892bSMathieu Poirier 	val = (unsigned long)config->vmid_val[config->vmid_idx];
2136bf0ef4f1SLeo Yan 	spin_unlock(&drvdata->spinlock);
2137a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
2138a77de263SMathieu Poirier }
2139a77de263SMathieu Poirier 
vmid_val_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)2140a77de263SMathieu Poirier static ssize_t vmid_val_store(struct device *dev,
2141a77de263SMathieu Poirier 			      struct device_attribute *attr,
2142a77de263SMathieu Poirier 			      const char *buf, size_t size)
2143a77de263SMathieu Poirier {
2144a77de263SMathieu Poirier 	unsigned long val;
2145a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
214654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
2147a77de263SMathieu Poirier 
2148a77de263SMathieu Poirier 	/*
21491314dd19SLeo Yan 	 * Don't use virtual contextID tracing if coming from a PID namespace.
21501314dd19SLeo Yan 	 * See comment in ctxid_pid_store().
21511314dd19SLeo Yan 	 */
21521314dd19SLeo Yan 	if (!task_is_in_init_pid_ns(current))
21531314dd19SLeo Yan 		return -EINVAL;
21541314dd19SLeo Yan 
21551314dd19SLeo Yan 	/*
2156a77de263SMathieu Poirier 	 * only implemented when vmid tracing is enabled, i.e. at least one
2157a77de263SMathieu Poirier 	 * vmid comparator is implemented and at least 8 bit vmid size
2158a77de263SMathieu Poirier 	 */
2159a77de263SMathieu Poirier 	if (!drvdata->vmid_size || !drvdata->numvmidc)
2160a77de263SMathieu Poirier 		return -EINVAL;
2161a77de263SMathieu Poirier 	if (kstrtoul(buf, 16, &val))
2162a77de263SMathieu Poirier 		return -EINVAL;
2163a77de263SMathieu Poirier 
2164a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
216554ff892bSMathieu Poirier 	config->vmid_val[config->vmid_idx] = (u64)val;
2166a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
2167a77de263SMathieu Poirier 	return size;
2168a77de263SMathieu Poirier }
2169a77de263SMathieu Poirier static DEVICE_ATTR_RW(vmid_val);
2170a77de263SMathieu Poirier 
vmid_masks_show(struct device * dev,struct device_attribute * attr,char * buf)2171a77de263SMathieu Poirier static ssize_t vmid_masks_show(struct device *dev,
2172a77de263SMathieu Poirier 			       struct device_attribute *attr, char *buf)
2173a77de263SMathieu Poirier {
2174a77de263SMathieu Poirier 	unsigned long val1, val2;
2175a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
217654ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
2177a77de263SMathieu Poirier 
21781314dd19SLeo Yan 	/*
21791314dd19SLeo Yan 	 * Don't use virtual contextID tracing if coming from a PID namespace.
21801314dd19SLeo Yan 	 * See comment in ctxid_pid_store().
21811314dd19SLeo Yan 	 */
21821314dd19SLeo Yan 	if (!task_is_in_init_pid_ns(current))
21831314dd19SLeo Yan 		return -EINVAL;
21841314dd19SLeo Yan 
2185a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
218654ff892bSMathieu Poirier 	val1 = config->vmid_mask0;
218754ff892bSMathieu Poirier 	val2 = config->vmid_mask1;
2188a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
2189a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
2190a77de263SMathieu Poirier }
2191a77de263SMathieu Poirier 
vmid_masks_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)2192a77de263SMathieu Poirier static ssize_t vmid_masks_store(struct device *dev,
2193a77de263SMathieu Poirier 				struct device_attribute *attr,
2194a77de263SMathieu Poirier 				const char *buf, size_t size)
2195a77de263SMathieu Poirier {
2196a77de263SMathieu Poirier 	u8 i, j, maskbyte;
2197a77de263SMathieu Poirier 	unsigned long val1, val2, mask;
2198a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
219954ff892bSMathieu Poirier 	struct etmv4_config *config = &drvdata->config;
22003e12d3b0SMike Leach 	int nr_inputs;
220154ff892bSMathieu Poirier 
2202a77de263SMathieu Poirier 	/*
22031314dd19SLeo Yan 	 * Don't use virtual contextID tracing if coming from a PID namespace.
22041314dd19SLeo Yan 	 * See comment in ctxid_pid_store().
22051314dd19SLeo Yan 	 */
22061314dd19SLeo Yan 	if (!task_is_in_init_pid_ns(current))
22071314dd19SLeo Yan 		return -EINVAL;
22081314dd19SLeo Yan 
22091314dd19SLeo Yan 	/*
2210a77de263SMathieu Poirier 	 * only implemented when vmid tracing is enabled, i.e. at least one
2211a77de263SMathieu Poirier 	 * vmid comparator is implemented and at least 8 bit vmid size
2212a77de263SMathieu Poirier 	 */
2213a77de263SMathieu Poirier 	if (!drvdata->vmid_size || !drvdata->numvmidc)
2214a77de263SMathieu Poirier 		return -EINVAL;
22153e12d3b0SMike Leach 	/* one mask if <= 4 comparators, two for up to 8 */
22163e12d3b0SMike Leach 	nr_inputs = sscanf(buf, "%lx %lx", &val1, &val2);
22173e12d3b0SMike Leach 	if ((drvdata->numvmidc > 4) && (nr_inputs != 2))
2218a77de263SMathieu Poirier 		return -EINVAL;
2219a77de263SMathieu Poirier 
2220a77de263SMathieu Poirier 	spin_lock(&drvdata->spinlock);
2221a77de263SMathieu Poirier 
2222a77de263SMathieu Poirier 	/*
2223a77de263SMathieu Poirier 	 * each byte[0..3] controls mask value applied to vmid
2224a77de263SMathieu Poirier 	 * comparator[0..3]
2225a77de263SMathieu Poirier 	 */
2226a77de263SMathieu Poirier 	switch (drvdata->numvmidc) {
2227a77de263SMathieu Poirier 	case 0x1:
2228a77de263SMathieu Poirier 		/* COMP0, bits[7:0] */
222954ff892bSMathieu Poirier 		config->vmid_mask0 = val1 & 0xFF;
2230a77de263SMathieu Poirier 		break;
2231a77de263SMathieu Poirier 	case 0x2:
2232a77de263SMathieu Poirier 		/* COMP1, bits[15:8] */
223354ff892bSMathieu Poirier 		config->vmid_mask0 = val1 & 0xFFFF;
2234a77de263SMathieu Poirier 		break;
2235a77de263SMathieu Poirier 	case 0x3:
2236a77de263SMathieu Poirier 		/* COMP2, bits[23:16] */
223754ff892bSMathieu Poirier 		config->vmid_mask0 = val1 & 0xFFFFFF;
2238a77de263SMathieu Poirier 		break;
2239a77de263SMathieu Poirier 	case 0x4:
2240a77de263SMathieu Poirier 		/* COMP3, bits[31:24] */
224154ff892bSMathieu Poirier 		config->vmid_mask0 = val1;
2242a77de263SMathieu Poirier 		break;
2243a77de263SMathieu Poirier 	case 0x5:
2244a77de263SMathieu Poirier 		/* COMP4, bits[7:0] */
224554ff892bSMathieu Poirier 		config->vmid_mask0 = val1;
224654ff892bSMathieu Poirier 		config->vmid_mask1 = val2 & 0xFF;
2247a77de263SMathieu Poirier 		break;
2248a77de263SMathieu Poirier 	case 0x6:
2249a77de263SMathieu Poirier 		/* COMP5, bits[15:8] */
225054ff892bSMathieu Poirier 		config->vmid_mask0 = val1;
225154ff892bSMathieu Poirier 		config->vmid_mask1 = val2 & 0xFFFF;
2252a77de263SMathieu Poirier 		break;
2253a77de263SMathieu Poirier 	case 0x7:
2254a77de263SMathieu Poirier 		/* COMP6, bits[23:16] */
225554ff892bSMathieu Poirier 		config->vmid_mask0 = val1;
225654ff892bSMathieu Poirier 		config->vmid_mask1 = val2 & 0xFFFFFF;
2257a77de263SMathieu Poirier 		break;
2258a77de263SMathieu Poirier 	case 0x8:
2259a77de263SMathieu Poirier 		/* COMP7, bits[31:24] */
226054ff892bSMathieu Poirier 		config->vmid_mask0 = val1;
226154ff892bSMathieu Poirier 		config->vmid_mask1 = val2;
2262a77de263SMathieu Poirier 		break;
2263a77de263SMathieu Poirier 	default:
2264a77de263SMathieu Poirier 		break;
2265a77de263SMathieu Poirier 	}
2266a77de263SMathieu Poirier 
2267a77de263SMathieu Poirier 	/*
2268a77de263SMathieu Poirier 	 * If software sets a mask bit to 1, it must program relevant byte
2269a77de263SMathieu Poirier 	 * of vmid comparator value 0x0, otherwise behavior is unpredictable.
2270a77de263SMathieu Poirier 	 * For example, if bit[3] of vmid_mask0 is 1, we must clear bits[31:24]
2271a77de263SMathieu Poirier 	 * of vmid comparator0 value (corresponding to byte 0) register.
2272a77de263SMathieu Poirier 	 */
227354ff892bSMathieu Poirier 	mask = config->vmid_mask0;
2274a77de263SMathieu Poirier 	for (i = 0; i < drvdata->numvmidc; i++) {
2275a77de263SMathieu Poirier 		/* mask value of corresponding vmid comparator */
2276a77de263SMathieu Poirier 		maskbyte = mask & ETMv4_EVENT_MASK;
2277a77de263SMathieu Poirier 		/*
2278a77de263SMathieu Poirier 		 * each bit corresponds to a byte of respective vmid comparator
2279a77de263SMathieu Poirier 		 * value register
2280a77de263SMathieu Poirier 		 */
2281a77de263SMathieu Poirier 		for (j = 0; j < 8; j++) {
2282a77de263SMathieu Poirier 			if (maskbyte & 1)
228357adbeeaSBo Yan 				config->vmid_val[i] &= ~(0xFFUL << (j * 8));
2284a77de263SMathieu Poirier 			maskbyte >>= 1;
2285a77de263SMathieu Poirier 		}
2286a77de263SMathieu Poirier 		/* Select the next vmid comparator mask value */
2287a77de263SMathieu Poirier 		if (i == 3)
2288a77de263SMathieu Poirier 			/* vmid comparators[4-7] */
228954ff892bSMathieu Poirier 			mask = config->vmid_mask1;
2290a77de263SMathieu Poirier 		else
2291a77de263SMathieu Poirier 			mask >>= 0x8;
2292a77de263SMathieu Poirier 	}
2293a77de263SMathieu Poirier 	spin_unlock(&drvdata->spinlock);
2294a77de263SMathieu Poirier 	return size;
2295a77de263SMathieu Poirier }
2296a77de263SMathieu Poirier static DEVICE_ATTR_RW(vmid_masks);
2297a77de263SMathieu Poirier 
cpu_show(struct device * dev,struct device_attribute * attr,char * buf)2298a77de263SMathieu Poirier static ssize_t cpu_show(struct device *dev,
2299a77de263SMathieu Poirier 			struct device_attribute *attr, char *buf)
2300a77de263SMathieu Poirier {
2301a77de263SMathieu Poirier 	int val;
2302a77de263SMathieu Poirier 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
2303a77de263SMathieu Poirier 
2304a77de263SMathieu Poirier 	val = drvdata->cpu;
2305a77de263SMathieu Poirier 	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
2306a77de263SMathieu Poirier 
2307a77de263SMathieu Poirier }
2308a77de263SMathieu Poirier static DEVICE_ATTR_RO(cpu);
2309a77de263SMathieu Poirier 
ts_source_show(struct device * dev,struct device_attribute * attr,char * buf)23100f00b223SGerman Gomez static ssize_t ts_source_show(struct device *dev,
23110f00b223SGerman Gomez 			      struct device_attribute *attr,
23120f00b223SGerman Gomez 			      char *buf)
23130f00b223SGerman Gomez {
23140f00b223SGerman Gomez 	int val;
23150f00b223SGerman Gomez 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
23160f00b223SGerman Gomez 
23170f00b223SGerman Gomez 	if (!drvdata->trfcr) {
23180f00b223SGerman Gomez 		val = -1;
23190f00b223SGerman Gomez 		goto out;
23200f00b223SGerman Gomez 	}
23210f00b223SGerman Gomez 
23220f00b223SGerman Gomez 	switch (drvdata->trfcr & TRFCR_ELx_TS_MASK) {
23230f00b223SGerman Gomez 	case TRFCR_ELx_TS_VIRTUAL:
23240f00b223SGerman Gomez 	case TRFCR_ELx_TS_GUEST_PHYSICAL:
23250f00b223SGerman Gomez 	case TRFCR_ELx_TS_PHYSICAL:
23260f00b223SGerman Gomez 		val = FIELD_GET(TRFCR_ELx_TS_MASK, drvdata->trfcr);
23270f00b223SGerman Gomez 		break;
23280f00b223SGerman Gomez 	default:
23290f00b223SGerman Gomez 		val = -1;
23300f00b223SGerman Gomez 		break;
23310f00b223SGerman Gomez 	}
23320f00b223SGerman Gomez 
23330f00b223SGerman Gomez out:
23340f00b223SGerman Gomez 	return sysfs_emit(buf, "%d\n", val);
23350f00b223SGerman Gomez }
23360f00b223SGerman Gomez static DEVICE_ATTR_RO(ts_source);
23370f00b223SGerman Gomez 
2338a77de263SMathieu Poirier static struct attribute *coresight_etmv4_attrs[] = {
2339a77de263SMathieu Poirier 	&dev_attr_nr_pe_cmp.attr,
2340a77de263SMathieu Poirier 	&dev_attr_nr_addr_cmp.attr,
2341a77de263SMathieu Poirier 	&dev_attr_nr_cntr.attr,
2342a77de263SMathieu Poirier 	&dev_attr_nr_ext_inp.attr,
2343a77de263SMathieu Poirier 	&dev_attr_numcidc.attr,
2344a77de263SMathieu Poirier 	&dev_attr_numvmidc.attr,
2345a77de263SMathieu Poirier 	&dev_attr_nrseqstate.attr,
2346a77de263SMathieu Poirier 	&dev_attr_nr_resource.attr,
2347a77de263SMathieu Poirier 	&dev_attr_nr_ss_cmp.attr,
2348a77de263SMathieu Poirier 	&dev_attr_reset.attr,
2349a77de263SMathieu Poirier 	&dev_attr_mode.attr,
2350a77de263SMathieu Poirier 	&dev_attr_pe.attr,
2351a77de263SMathieu Poirier 	&dev_attr_event.attr,
2352a77de263SMathieu Poirier 	&dev_attr_event_instren.attr,
2353a77de263SMathieu Poirier 	&dev_attr_event_ts.attr,
2354a77de263SMathieu Poirier 	&dev_attr_syncfreq.attr,
2355a77de263SMathieu Poirier 	&dev_attr_cyc_threshold.attr,
2356a77de263SMathieu Poirier 	&dev_attr_bb_ctrl.attr,
2357a77de263SMathieu Poirier 	&dev_attr_event_vinst.attr,
2358a77de263SMathieu Poirier 	&dev_attr_s_exlevel_vinst.attr,
2359a77de263SMathieu Poirier 	&dev_attr_ns_exlevel_vinst.attr,
2360a77de263SMathieu Poirier 	&dev_attr_addr_idx.attr,
2361a77de263SMathieu Poirier 	&dev_attr_addr_instdatatype.attr,
2362a77de263SMathieu Poirier 	&dev_attr_addr_single.attr,
2363a77de263SMathieu Poirier 	&dev_attr_addr_range.attr,
2364a77de263SMathieu Poirier 	&dev_attr_addr_start.attr,
2365a77de263SMathieu Poirier 	&dev_attr_addr_stop.attr,
2366a77de263SMathieu Poirier 	&dev_attr_addr_ctxtype.attr,
2367a77de263SMathieu Poirier 	&dev_attr_addr_context.attr,
236875198a7dSMike Leach 	&dev_attr_addr_exlevel_s_ns.attr,
2369a578427dSMike Leach 	&dev_attr_addr_cmp_view.attr,
23701b6b0e08SMike Leach 	&dev_attr_vinst_pe_cmp_start_stop.attr,
2371ebddaad0SMike Leach 	&dev_attr_sshot_idx.attr,
2372ebddaad0SMike Leach 	&dev_attr_sshot_ctrl.attr,
2373ebddaad0SMike Leach 	&dev_attr_sshot_pe_ctrl.attr,
2374ebddaad0SMike Leach 	&dev_attr_sshot_status.attr,
2375a77de263SMathieu Poirier 	&dev_attr_seq_idx.attr,
2376a77de263SMathieu Poirier 	&dev_attr_seq_state.attr,
2377a77de263SMathieu Poirier 	&dev_attr_seq_event.attr,
2378a77de263SMathieu Poirier 	&dev_attr_seq_reset_event.attr,
2379a77de263SMathieu Poirier 	&dev_attr_cntr_idx.attr,
2380a77de263SMathieu Poirier 	&dev_attr_cntrldvr.attr,
2381a77de263SMathieu Poirier 	&dev_attr_cntr_val.attr,
2382a77de263SMathieu Poirier 	&dev_attr_cntr_ctrl.attr,
2383a77de263SMathieu Poirier 	&dev_attr_res_idx.attr,
2384a77de263SMathieu Poirier 	&dev_attr_res_ctrl.attr,
2385a77de263SMathieu Poirier 	&dev_attr_ctxid_idx.attr,
2386a77de263SMathieu Poirier 	&dev_attr_ctxid_pid.attr,
2387a77de263SMathieu Poirier 	&dev_attr_ctxid_masks.attr,
2388a77de263SMathieu Poirier 	&dev_attr_vmid_idx.attr,
2389a77de263SMathieu Poirier 	&dev_attr_vmid_val.attr,
2390a77de263SMathieu Poirier 	&dev_attr_vmid_masks.attr,
2391a77de263SMathieu Poirier 	&dev_attr_cpu.attr,
23920f00b223SGerman Gomez 	&dev_attr_ts_source.attr,
2393a77de263SMathieu Poirier 	NULL,
2394a77de263SMathieu Poirier };
2395a77de263SMathieu Poirier 
2396df487120SMike Leach /*
2397df487120SMike Leach  * Trace ID allocated dynamically on enable - but also allocate on read
2398df487120SMike Leach  * in case sysfs or perf read before enable to ensure consistent metadata
2399df487120SMike Leach  * information for trace decode
2400df487120SMike Leach  */
trctraceid_show(struct device * dev,struct device_attribute * attr,char * buf)2401df487120SMike Leach static ssize_t trctraceid_show(struct device *dev,
2402df487120SMike Leach 			       struct device_attribute *attr,
2403df487120SMike Leach 			       char *buf)
2404df487120SMike Leach {
2405df487120SMike Leach 	int trace_id;
2406df487120SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
2407df487120SMike Leach 
2408df487120SMike Leach 	trace_id = etm4_read_alloc_trace_id(drvdata);
2409df487120SMike Leach 	if (trace_id < 0)
2410df487120SMike Leach 		return trace_id;
2411df487120SMike Leach 
2412df487120SMike Leach 	return sysfs_emit(buf, "0x%x\n", trace_id);
2413df487120SMike Leach }
2414df487120SMike Leach 
24153224dcc5SSudeep Holla struct etmv4_reg {
2416f5bd5236SSuzuki K Poulose 	struct coresight_device *csdev;
2417f5bd5236SSuzuki K Poulose 	u32 offset;
24183224dcc5SSudeep Holla 	u32 data;
24193224dcc5SSudeep Holla };
2420a77de263SMathieu Poirier 
do_smp_cross_read(void * data)24213224dcc5SSudeep Holla static void do_smp_cross_read(void *data)
24223224dcc5SSudeep Holla {
24233224dcc5SSudeep Holla 	struct etmv4_reg *reg = data;
24243224dcc5SSudeep Holla 
2425f5bd5236SSuzuki K Poulose 	reg->data = etm4x_relaxed_read32(&reg->csdev->access, reg->offset);
24263224dcc5SSudeep Holla }
24273224dcc5SSudeep Holla 
etmv4_cross_read(const struct etmv4_drvdata * drvdata,u32 offset)2428c03ceec1SSuzuki K Poulose static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
24293224dcc5SSudeep Holla {
24303224dcc5SSudeep Holla 	struct etmv4_reg reg;
24313224dcc5SSudeep Holla 
2432f5bd5236SSuzuki K Poulose 	reg.offset = offset;
2433f5bd5236SSuzuki K Poulose 	reg.csdev = drvdata->csdev;
2434f5bd5236SSuzuki K Poulose 
24353224dcc5SSudeep Holla 	/*
24363224dcc5SSudeep Holla 	 * smp cross call ensures the CPU will be powered up before
24373224dcc5SSudeep Holla 	 * accessing the ETMv4 trace core registers
24383224dcc5SSudeep Holla 	 */
24393224dcc5SSudeep Holla 	smp_call_function_single(drvdata->cpu, do_smp_cross_read, &reg, 1);
24403224dcc5SSudeep Holla 	return reg.data;
24413224dcc5SSudeep Holla }
24423224dcc5SSudeep Holla 
coresight_etm4x_attr_to_offset(struct device_attribute * attr)2443c03ceec1SSuzuki K Poulose static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
2444c03ceec1SSuzuki K Poulose {
2445c03ceec1SSuzuki K Poulose 	struct dev_ext_attribute *eattr;
24463224dcc5SSudeep Holla 
2447c03ceec1SSuzuki K Poulose 	eattr = container_of(attr, struct dev_ext_attribute, attr);
2448c03ceec1SSuzuki K Poulose 	return (u32)(unsigned long)eattr->var;
2449c03ceec1SSuzuki K Poulose }
2450c03ceec1SSuzuki K Poulose 
coresight_etm4x_reg_show(struct device * dev,struct device_attribute * d_attr,char * buf)2451c03ceec1SSuzuki K Poulose static ssize_t coresight_etm4x_reg_show(struct device *dev,
2452c03ceec1SSuzuki K Poulose 					struct device_attribute *d_attr,
2453c03ceec1SSuzuki K Poulose 					char *buf)
2454c03ceec1SSuzuki K Poulose {
2455c03ceec1SSuzuki K Poulose 	u32 val, offset;
2456c03ceec1SSuzuki K Poulose 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
2457c03ceec1SSuzuki K Poulose 
2458c03ceec1SSuzuki K Poulose 	offset = coresight_etm4x_attr_to_offset(d_attr);
2459c03ceec1SSuzuki K Poulose 
2460c03ceec1SSuzuki K Poulose 	pm_runtime_get_sync(dev->parent);
2461c03ceec1SSuzuki K Poulose 	val = etmv4_cross_read(drvdata, offset);
2462c03ceec1SSuzuki K Poulose 	pm_runtime_put_sync(dev->parent);
2463c03ceec1SSuzuki K Poulose 
2464c03ceec1SSuzuki K Poulose 	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
2465c03ceec1SSuzuki K Poulose }
2466c03ceec1SSuzuki K Poulose 
246791b9f018SSuzuki K Poulose static inline bool
etm4x_register_implemented(struct etmv4_drvdata * drvdata,u32 offset)246891b9f018SSuzuki K Poulose etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
246991b9f018SSuzuki K Poulose {
247091b9f018SSuzuki K Poulose 	switch (offset) {
247135e1c916SSuzuki K Poulose 	ETM_COMMON_SYSREG_LIST_CASES
247291b9f018SSuzuki K Poulose 		/*
247335e1c916SSuzuki K Poulose 		 * Common registers to ETE & ETM4x accessible via system
247435e1c916SSuzuki K Poulose 		 * instructions are always implemented.
247591b9f018SSuzuki K Poulose 		 */
247691b9f018SSuzuki K Poulose 		return true;
247735e1c916SSuzuki K Poulose 
247835e1c916SSuzuki K Poulose 	ETM4x_ONLY_SYSREG_LIST_CASES
247935e1c916SSuzuki K Poulose 		/*
248035e1c916SSuzuki K Poulose 		 * We only support etm4x and ete. So if the device is not
248135e1c916SSuzuki K Poulose 		 * ETE, it must be ETMv4x.
248235e1c916SSuzuki K Poulose 		 */
248335e1c916SSuzuki K Poulose 		return !etm4x_is_ete(drvdata);
248435e1c916SSuzuki K Poulose 
248591b9f018SSuzuki K Poulose 	ETM4x_MMAP_LIST_CASES
248691b9f018SSuzuki K Poulose 		/*
248791b9f018SSuzuki K Poulose 		 * Registers accessible only via memory-mapped registers
248891b9f018SSuzuki K Poulose 		 * must not be accessed via system instructions.
248991b9f018SSuzuki K Poulose 		 * We cannot access the drvdata->csdev here, as this
249091b9f018SSuzuki K Poulose 		 * function is called during the device creation, via
249191b9f018SSuzuki K Poulose 		 * coresight_register() and the csdev is not initialized
249291b9f018SSuzuki K Poulose 		 * until that is done. So rely on the drvdata->base to
249391b9f018SSuzuki K Poulose 		 * detect if we have a memory mapped access.
249435e1c916SSuzuki K Poulose 		 * Also ETE doesn't implement memory mapped access, thus
249535e1c916SSuzuki K Poulose 		 * it is sufficient to check that we are using mmio.
249691b9f018SSuzuki K Poulose 		 */
249791b9f018SSuzuki K Poulose 		return !!drvdata->base;
249835e1c916SSuzuki K Poulose 
249935e1c916SSuzuki K Poulose 	ETE_ONLY_SYSREG_LIST_CASES
250035e1c916SSuzuki K Poulose 		return etm4x_is_ete(drvdata);
250191b9f018SSuzuki K Poulose 	}
250291b9f018SSuzuki K Poulose 
250391b9f018SSuzuki K Poulose 	return false;
250491b9f018SSuzuki K Poulose }
250591b9f018SSuzuki K Poulose 
250691b9f018SSuzuki K Poulose /*
250791b9f018SSuzuki K Poulose  * Hide the ETM4x registers that may not be available on the
250891b9f018SSuzuki K Poulose  * hardware.
250991b9f018SSuzuki K Poulose  * There are certain management registers unavailable via system
251091b9f018SSuzuki K Poulose  * instructions. Make those sysfs attributes hidden on such
251191b9f018SSuzuki K Poulose  * systems.
251291b9f018SSuzuki K Poulose  */
251391b9f018SSuzuki K Poulose static umode_t
coresight_etm4x_attr_reg_implemented(struct kobject * kobj,struct attribute * attr,int unused)251491b9f018SSuzuki K Poulose coresight_etm4x_attr_reg_implemented(struct kobject *kobj,
251591b9f018SSuzuki K Poulose 				     struct attribute *attr, int unused)
251691b9f018SSuzuki K Poulose {
251791b9f018SSuzuki K Poulose 	struct device *dev = kobj_to_dev(kobj);
251891b9f018SSuzuki K Poulose 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
251991b9f018SSuzuki K Poulose 	struct device_attribute *d_attr;
252091b9f018SSuzuki K Poulose 	u32 offset;
252191b9f018SSuzuki K Poulose 
252291b9f018SSuzuki K Poulose 	d_attr = container_of(attr, struct device_attribute, attr);
252391b9f018SSuzuki K Poulose 	offset = coresight_etm4x_attr_to_offset(d_attr);
252491b9f018SSuzuki K Poulose 
252591b9f018SSuzuki K Poulose 	if (etm4x_register_implemented(drvdata, offset))
252691b9f018SSuzuki K Poulose 		return attr->mode;
252791b9f018SSuzuki K Poulose 	return 0;
252891b9f018SSuzuki K Poulose }
252991b9f018SSuzuki K Poulose 
2530*9f37d379SMike Leach /*
2531*9f37d379SMike Leach  * Macro to set an RO ext attribute with offset and show function.
2532*9f37d379SMike Leach  * Offset is used in mgmt group to ensure only correct registers for
2533*9f37d379SMike Leach  * the ETM / ETE variant are visible.
2534*9f37d379SMike Leach  */
2535*9f37d379SMike Leach #define coresight_etm4x_reg_showfn(name, offset, showfn) (	\
2536c03ceec1SSuzuki K Poulose 	&((struct dev_ext_attribute[]) {			\
2537c03ceec1SSuzuki K Poulose 	   {							\
2538*9f37d379SMike Leach 		__ATTR(name, 0444, showfn, NULL),		\
2539c03ceec1SSuzuki K Poulose 		(void *)(unsigned long)offset			\
2540c03ceec1SSuzuki K Poulose 	   }							\
2541*9f37d379SMike Leach 	})[0].attr.attr						\
2542*9f37d379SMike Leach 	)
2543*9f37d379SMike Leach 
2544*9f37d379SMike Leach /* macro using the default coresight_etm4x_reg_show function */
2545*9f37d379SMike Leach #define coresight_etm4x_reg(name, offset)	\
2546*9f37d379SMike Leach 	coresight_etm4x_reg_showfn(name, offset, coresight_etm4x_reg_show)
2547a77de263SMathieu Poirier 
2548a77de263SMathieu Poirier static struct attribute *coresight_etmv4_mgmt_attrs[] = {
2549c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcpdcr, TRCPDCR),
2550c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcpdsr, TRCPDSR),
2551c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trclsr, TRCLSR),
2552c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS),
2553c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcdevid, TRCDEVID),
2554c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcdevtype, TRCDEVTYPE),
2555c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcpidr0, TRCPIDR0),
2556c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcpidr1, TRCPIDR1),
2557c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcpidr2, TRCPIDR2),
2558c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcpidr3, TRCPIDR3),
2559c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcoslsr, TRCOSLSR),
2560c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcconfig, TRCCONFIGR),
2561*9f37d379SMike Leach 	coresight_etm4x_reg_showfn(trctraceid, TRCTRACEIDR, trctraceid_show),
25624211bfceSSuzuki K Poulose 	coresight_etm4x_reg(trcdevarch, TRCDEVARCH),
2563a77de263SMathieu Poirier 	NULL,
2564a77de263SMathieu Poirier };
2565a77de263SMathieu Poirier 
2566a77de263SMathieu Poirier static struct attribute *coresight_etmv4_trcidr_attrs[] = {
2567c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr0, TRCIDR0),
2568c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr1, TRCIDR1),
2569c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr2, TRCIDR2),
2570c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr3, TRCIDR3),
2571c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr4, TRCIDR4),
2572c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr5, TRCIDR5),
2573a77de263SMathieu Poirier 	/* trcidr[6,7] are reserved */
2574c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr8, TRCIDR8),
2575c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr9, TRCIDR9),
2576c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr10, TRCIDR10),
2577c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr11, TRCIDR11),
2578c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr12, TRCIDR12),
2579c03ceec1SSuzuki K Poulose 	coresight_etm4x_reg(trcidr13, TRCIDR13),
2580a77de263SMathieu Poirier 	NULL,
2581a77de263SMathieu Poirier };
2582a77de263SMathieu Poirier 
2583a77de263SMathieu Poirier static const struct attribute_group coresight_etmv4_group = {
2584a77de263SMathieu Poirier 	.attrs = coresight_etmv4_attrs,
2585a77de263SMathieu Poirier };
2586a77de263SMathieu Poirier 
2587a77de263SMathieu Poirier static const struct attribute_group coresight_etmv4_mgmt_group = {
258891b9f018SSuzuki K Poulose 	.is_visible = coresight_etm4x_attr_reg_implemented,
2589a77de263SMathieu Poirier 	.attrs = coresight_etmv4_mgmt_attrs,
2590a77de263SMathieu Poirier 	.name = "mgmt",
2591a77de263SMathieu Poirier };
2592a77de263SMathieu Poirier 
2593a77de263SMathieu Poirier static const struct attribute_group coresight_etmv4_trcidr_group = {
2594a77de263SMathieu Poirier 	.attrs = coresight_etmv4_trcidr_attrs,
2595a77de263SMathieu Poirier 	.name = "trcidr",
2596a77de263SMathieu Poirier };
2597a77de263SMathieu Poirier 
2598a77de263SMathieu Poirier const struct attribute_group *coresight_etmv4_groups[] = {
2599a77de263SMathieu Poirier 	&coresight_etmv4_group,
2600a77de263SMathieu Poirier 	&coresight_etmv4_mgmt_group,
2601a77de263SMathieu Poirier 	&coresight_etmv4_trcidr_group,
2602a77de263SMathieu Poirier 	NULL,
2603a77de263SMathieu Poirier };
2604