xref: /linux/drivers/hwtracing/coresight/coresight-etm4x-core.c (revision 594ce0b8a998aa4d05827cd7c0d0dcec9a1e3ae2)
122a550a3SKim Phillips // SPDX-License-Identifier: GPL-2.0
222a550a3SKim Phillips /*
322a550a3SKim Phillips  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
422a550a3SKim Phillips  */
522a550a3SKim Phillips 
6134124acSSuzuki K Poulose #include <linux/acpi.h>
7e7255092SQi Liu #include <linux/bitops.h>
822a550a3SKim Phillips #include <linux/kernel.h>
922a550a3SKim Phillips #include <linux/moduleparam.h>
1022a550a3SKim Phillips #include <linux/init.h>
1122a550a3SKim Phillips #include <linux/types.h>
1222a550a3SKim Phillips #include <linux/device.h>
1322a550a3SKim Phillips #include <linux/io.h>
1422a550a3SKim Phillips #include <linux/err.h>
1522a550a3SKim Phillips #include <linux/fs.h>
1622a550a3SKim Phillips #include <linux/slab.h>
1722a550a3SKim Phillips #include <linux/delay.h>
1822a550a3SKim Phillips #include <linux/smp.h>
1922a550a3SKim Phillips #include <linux/sysfs.h>
2022a550a3SKim Phillips #include <linux/stat.h>
2122a550a3SKim Phillips #include <linux/clk.h>
2222a550a3SKim Phillips #include <linux/cpu.h>
2322a550a3SKim Phillips #include <linux/cpu_pm.h>
2422a550a3SKim Phillips #include <linux/coresight.h>
2522a550a3SKim Phillips #include <linux/coresight-pmu.h>
2622a550a3SKim Phillips #include <linux/pm_wakeup.h>
2722a550a3SKim Phillips #include <linux/amba/bus.h>
2822a550a3SKim Phillips #include <linux/seq_file.h>
2922a550a3SKim Phillips #include <linux/uaccess.h>
3022a550a3SKim Phillips #include <linux/perf_event.h>
315214b563SSuzuki K Poulose #include <linux/platform_device.h>
3222a550a3SKim Phillips #include <linux/pm_runtime.h>
3322a550a3SKim Phillips #include <linux/property.h>
3473d779a0SAnshuman Khandual #include <linux/clk/clk-conf.h>
35e7255092SQi Liu 
368b481196SSuzuki K Poulose #include <asm/barrier.h>
3722a550a3SKim Phillips #include <asm/sections.h>
38e7255092SQi Liu #include <asm/sysreg.h>
3922a550a3SKim Phillips #include <asm/local.h>
4022a550a3SKim Phillips #include <asm/virt.h>
4122a550a3SKim Phillips 
4222a550a3SKim Phillips #include "coresight-etm4x.h"
4322a550a3SKim Phillips #include "coresight-etm-perf.h"
44810ac401SMike Leach #include "coresight-etm4x-cfg.h"
45937d3f58SSuzuki K Poulose #include "coresight-self-hosted-trace.h"
46810ac401SMike Leach #include "coresight-syscfg.h"
47df487120SMike Leach #include "coresight-trace-id.h"
4822a550a3SKim Phillips 
4922a550a3SKim Phillips static int boot_enable;
5022a550a3SKim Phillips module_param(boot_enable, int, 0444);
5122a550a3SKim Phillips MODULE_PARM_DESC(boot_enable, "Enable tracing on boot");
5222a550a3SKim Phillips 
5322a550a3SKim Phillips #define PARAM_PM_SAVE_FIRMWARE	  0 /* save self-hosted state as per firmware */
5422a550a3SKim Phillips #define PARAM_PM_SAVE_NEVER	  1 /* never save any state */
5522a550a3SKim Phillips #define PARAM_PM_SAVE_SELF_HOSTED 2 /* save self-hosted state only */
5622a550a3SKim Phillips 
5722a550a3SKim Phillips static int pm_save_enable = PARAM_PM_SAVE_FIRMWARE;
5822a550a3SKim Phillips module_param(pm_save_enable, int, 0444);
5922a550a3SKim Phillips MODULE_PARM_DESC(pm_save_enable,
6022a550a3SKim Phillips 	"Save/restore state on power down: 1 = never, 2 = self-hosted");
6122a550a3SKim Phillips 
6222a550a3SKim Phillips static struct etmv4_drvdata *etmdrvdata[NR_CPUS];
6322a550a3SKim Phillips static void etm4_set_default_config(struct etmv4_config *config);
6422a550a3SKim Phillips static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
6522a550a3SKim Phillips 				  struct perf_event *event);
6622a550a3SKim Phillips static u64 etm4_get_access_type(struct etmv4_config *config);
6722a550a3SKim Phillips 
6822a550a3SKim Phillips static enum cpuhp_state hp_online;
6922a550a3SKim Phillips 
70fd6e7905SSuzuki K Poulose struct etm4_init_arg {
713c728e07STamas Zsoldos 	struct device		*dev;
72fd6e7905SSuzuki K Poulose 	struct csdev_access	*csa;
73fd6e7905SSuzuki K Poulose };
74fd6e7905SSuzuki K Poulose 
753c728e07STamas Zsoldos static DEFINE_PER_CPU(struct etm4_init_arg *, delayed_probe);
763c728e07STamas Zsoldos static int etm4_probe_cpu(unsigned int cpu);
773c728e07STamas Zsoldos 
78f6a18f35SSuzuki K Poulose /*
79f6a18f35SSuzuki K Poulose  * Check if TRCSSPCICRn(i) is implemented for a given instance.
80f6a18f35SSuzuki K Poulose  *
81f6a18f35SSuzuki K Poulose  * TRCSSPCICRn is implemented only if :
82f6a18f35SSuzuki K Poulose  *	TRCSSPCICR<n> is present only if all of the following are true:
83f6a18f35SSuzuki K Poulose  *		TRCIDR4.NUMSSCC > n.
84f6a18f35SSuzuki K Poulose  *		TRCIDR4.NUMPC > 0b0000 .
85f6a18f35SSuzuki K Poulose  *		TRCSSCSR<n>.PC == 0b1
86f6a18f35SSuzuki K Poulose  */
87f6a18f35SSuzuki K Poulose static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
88f6a18f35SSuzuki K Poulose {
89f6a18f35SSuzuki K Poulose 	return (n < drvdata->nr_ss_cmp) &&
90f6a18f35SSuzuki K Poulose 	       drvdata->nr_pe &&
91f6a18f35SSuzuki K Poulose 	       (drvdata->config.ss_status[n] & TRCSSCSRn_PC);
92f6a18f35SSuzuki K Poulose }
93f6a18f35SSuzuki K Poulose 
9403336d0fSSuzuki K Poulose u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit)
9503336d0fSSuzuki K Poulose {
9603336d0fSSuzuki K Poulose 	u64 res = 0;
9703336d0fSSuzuki K Poulose 
9803336d0fSSuzuki K Poulose 	switch (offset) {
9903336d0fSSuzuki K Poulose 	ETM4x_READ_SYSREG_CASES(res)
10003336d0fSSuzuki K Poulose 	default :
10103336d0fSSuzuki K Poulose 		pr_warn_ratelimited("etm4x: trying to read unsupported register @%x\n",
10203336d0fSSuzuki K Poulose 			 offset);
10303336d0fSSuzuki K Poulose 	}
10403336d0fSSuzuki K Poulose 
10503336d0fSSuzuki K Poulose 	if (!_relaxed)
106018b741eSSai Prakash Ranjan 		__io_ar(res);	/* Imitate the !relaxed I/O helpers */
10703336d0fSSuzuki K Poulose 
10803336d0fSSuzuki K Poulose 	return res;
10903336d0fSSuzuki K Poulose }
11003336d0fSSuzuki K Poulose 
11103336d0fSSuzuki K Poulose void etm4x_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit)
11203336d0fSSuzuki K Poulose {
11303336d0fSSuzuki K Poulose 	if (!_relaxed)
114018b741eSSai Prakash Ranjan 		__io_bw();	/* Imitate the !relaxed I/O helpers */
11503336d0fSSuzuki K Poulose 	if (!_64bit)
11603336d0fSSuzuki K Poulose 		val &= GENMASK(31, 0);
11703336d0fSSuzuki K Poulose 
11803336d0fSSuzuki K Poulose 	switch (offset) {
11903336d0fSSuzuki K Poulose 	ETM4x_WRITE_SYSREG_CASES(val)
12003336d0fSSuzuki K Poulose 	default :
12103336d0fSSuzuki K Poulose 		pr_warn_ratelimited("etm4x: trying to write to unsupported register @%x\n",
12203336d0fSSuzuki K Poulose 			offset);
12303336d0fSSuzuki K Poulose 	}
12403336d0fSSuzuki K Poulose }
12503336d0fSSuzuki K Poulose 
1263e666ad0SSuzuki K Poulose static u64 ete_sysreg_read(u32 offset, bool _relaxed, bool _64bit)
12722a550a3SKim Phillips {
1283e666ad0SSuzuki K Poulose 	u64 res = 0;
1293e666ad0SSuzuki K Poulose 
1303e666ad0SSuzuki K Poulose 	switch (offset) {
1313e666ad0SSuzuki K Poulose 	ETE_READ_CASES(res)
1323e666ad0SSuzuki K Poulose 	default :
1333e666ad0SSuzuki K Poulose 		pr_warn_ratelimited("ete: trying to read unsupported register @%x\n",
1343e666ad0SSuzuki K Poulose 				    offset);
1353e666ad0SSuzuki K Poulose 	}
1363e666ad0SSuzuki K Poulose 
1373e666ad0SSuzuki K Poulose 	if (!_relaxed)
138018b741eSSai Prakash Ranjan 		__io_ar(res);	/* Imitate the !relaxed I/O helpers */
1393e666ad0SSuzuki K Poulose 
1403e666ad0SSuzuki K Poulose 	return res;
1413e666ad0SSuzuki K Poulose }
1423e666ad0SSuzuki K Poulose 
1433e666ad0SSuzuki K Poulose static void ete_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit)
1443e666ad0SSuzuki K Poulose {
1453e666ad0SSuzuki K Poulose 	if (!_relaxed)
146018b741eSSai Prakash Ranjan 		__io_bw();	/* Imitate the !relaxed I/O helpers */
1473e666ad0SSuzuki K Poulose 	if (!_64bit)
1483e666ad0SSuzuki K Poulose 		val &= GENMASK(31, 0);
1493e666ad0SSuzuki K Poulose 
1503e666ad0SSuzuki K Poulose 	switch (offset) {
1513e666ad0SSuzuki K Poulose 	ETE_WRITE_CASES(val)
1523e666ad0SSuzuki K Poulose 	default :
1533e666ad0SSuzuki K Poulose 		pr_warn_ratelimited("ete: trying to write to unsupported register @%x\n",
1543e666ad0SSuzuki K Poulose 				    offset);
1553e666ad0SSuzuki K Poulose 	}
1563e666ad0SSuzuki K Poulose }
1573e666ad0SSuzuki K Poulose 
158bc2c689fSSuzuki K Poulose static void etm_detect_os_lock(struct etmv4_drvdata *drvdata,
159bc2c689fSSuzuki K Poulose 			       struct csdev_access *csa)
16022a550a3SKim Phillips {
161bc2c689fSSuzuki K Poulose 	u32 oslsr = etm4x_relaxed_read32(csa, TRCOSLSR);
162bc2c689fSSuzuki K Poulose 
163bc2c689fSSuzuki K Poulose 	drvdata->os_lock_model = ETM_OSLSR_OSLM(oslsr);
164bc2c689fSSuzuki K Poulose }
165bc2c689fSSuzuki K Poulose 
166bc2c689fSSuzuki K Poulose static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
167bc2c689fSSuzuki K Poulose 			      struct csdev_access *csa, u32 val)
168bc2c689fSSuzuki K Poulose {
169bc2c689fSSuzuki K Poulose 	val = !!val;
170bc2c689fSSuzuki K Poulose 
171bc2c689fSSuzuki K Poulose 	switch (drvdata->os_lock_model) {
172bc2c689fSSuzuki K Poulose 	case ETM_OSLOCK_PRESENT:
173bc2c689fSSuzuki K Poulose 		etm4x_relaxed_write32(csa, val, TRCOSLAR);
174bc2c689fSSuzuki K Poulose 		break;
175bc2c689fSSuzuki K Poulose 	case ETM_OSLOCK_PE:
176bc2c689fSSuzuki K Poulose 		write_sysreg_s(val, SYS_OSLAR_EL1);
177bc2c689fSSuzuki K Poulose 		break;
178bc2c689fSSuzuki K Poulose 	default:
179bc2c689fSSuzuki K Poulose 		pr_warn_once("CPU%d: Unsupported Trace OSLock model: %x\n",
180bc2c689fSSuzuki K Poulose 			     smp_processor_id(), drvdata->os_lock_model);
181bc2c689fSSuzuki K Poulose 		fallthrough;
182bc2c689fSSuzuki K Poulose 	case ETM_OSLOCK_NI:
183bc2c689fSSuzuki K Poulose 		return;
184bc2c689fSSuzuki K Poulose 	}
18522a550a3SKim Phillips 	isb();
18622a550a3SKim Phillips }
18722a550a3SKim Phillips 
188bc2c689fSSuzuki K Poulose static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
189bc2c689fSSuzuki K Poulose 				      struct csdev_access *csa)
190bc2c689fSSuzuki K Poulose {
191bc2c689fSSuzuki K Poulose 	WARN_ON(drvdata->cpu != smp_processor_id());
192bc2c689fSSuzuki K Poulose 
193bc2c689fSSuzuki K Poulose 	/* Writing 0 to OS Lock unlocks the trace unit registers */
194bc2c689fSSuzuki K Poulose 	etm_write_os_lock(drvdata, csa, 0x0);
195bc2c689fSSuzuki K Poulose 	drvdata->os_unlock = true;
196bc2c689fSSuzuki K Poulose }
197bc2c689fSSuzuki K Poulose 
198f5bd5236SSuzuki K Poulose static void etm4_os_unlock(struct etmv4_drvdata *drvdata)
199f5bd5236SSuzuki K Poulose {
200f5bd5236SSuzuki K Poulose 	if (!WARN_ON(!drvdata->csdev))
201f5bd5236SSuzuki K Poulose 		etm4_os_unlock_csa(drvdata, &drvdata->csdev->access);
202f5bd5236SSuzuki K Poulose }
203f5bd5236SSuzuki K Poulose 
20422a550a3SKim Phillips static void etm4_os_lock(struct etmv4_drvdata *drvdata)
20522a550a3SKim Phillips {
206f5bd5236SSuzuki K Poulose 	if (WARN_ON(!drvdata->csdev))
207f5bd5236SSuzuki K Poulose 		return;
208bc2c689fSSuzuki K Poulose 	/* Writing 0x1 to OS Lock locks the trace registers */
209bc2c689fSSuzuki K Poulose 	etm_write_os_lock(drvdata, &drvdata->csdev->access, 0x1);
21022a550a3SKim Phillips 	drvdata->os_unlock = false;
21122a550a3SKim Phillips }
21222a550a3SKim Phillips 
21333d5573aSSuzuki K Poulose static void etm4_cs_lock(struct etmv4_drvdata *drvdata,
21433d5573aSSuzuki K Poulose 			 struct csdev_access *csa)
21533d5573aSSuzuki K Poulose {
21633d5573aSSuzuki K Poulose 	/* Software Lock is only accessible via memory mapped interface */
21733d5573aSSuzuki K Poulose 	if (csa->io_mem)
21833d5573aSSuzuki K Poulose 		CS_LOCK(csa->base);
21933d5573aSSuzuki K Poulose }
22033d5573aSSuzuki K Poulose 
22133d5573aSSuzuki K Poulose static void etm4_cs_unlock(struct etmv4_drvdata *drvdata,
22233d5573aSSuzuki K Poulose 			   struct csdev_access *csa)
22333d5573aSSuzuki K Poulose {
22433d5573aSSuzuki K Poulose 	if (csa->io_mem)
22533d5573aSSuzuki K Poulose 		CS_UNLOCK(csa->base);
22633d5573aSSuzuki K Poulose }
22733d5573aSSuzuki K Poulose 
22822a550a3SKim Phillips static int etm4_cpu_id(struct coresight_device *csdev)
22922a550a3SKim Phillips {
23022a550a3SKim Phillips 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
23122a550a3SKim Phillips 
23222a550a3SKim Phillips 	return drvdata->cpu;
23322a550a3SKim Phillips }
23422a550a3SKim Phillips 
235df487120SMike Leach int etm4_read_alloc_trace_id(struct etmv4_drvdata *drvdata)
236df487120SMike Leach {
237df487120SMike Leach 	int trace_id;
238df487120SMike Leach 
239df487120SMike Leach 	/*
240df487120SMike Leach 	 * This will allocate a trace ID to the cpu,
241df487120SMike Leach 	 * or return the one currently allocated.
242df487120SMike Leach 	 * The trace id function has its own lock
243df487120SMike Leach 	 */
244df487120SMike Leach 	trace_id = coresight_trace_id_get_cpu_id(drvdata->cpu);
245df487120SMike Leach 	if (IS_VALID_CS_TRACE_ID(trace_id))
246df487120SMike Leach 		drvdata->trcid = (u8)trace_id;
247df487120SMike Leach 	else
248df487120SMike Leach 		dev_err(&drvdata->csdev->dev,
249df487120SMike Leach 			"Failed to allocate trace ID for %s on CPU%d\n",
250df487120SMike Leach 			dev_name(&drvdata->csdev->dev), drvdata->cpu);
251df487120SMike Leach 	return trace_id;
252df487120SMike Leach }
253df487120SMike Leach 
254df487120SMike Leach void etm4_release_trace_id(struct etmv4_drvdata *drvdata)
255df487120SMike Leach {
256df487120SMike Leach 	coresight_trace_id_put_cpu_id(drvdata->cpu);
257df487120SMike Leach }
258df487120SMike Leach 
25922a550a3SKim Phillips struct etm4_enable_arg {
26022a550a3SKim Phillips 	struct etmv4_drvdata *drvdata;
26122a550a3SKim Phillips 	int rc;
26222a550a3SKim Phillips };
26322a550a3SKim Phillips 
2645f6fd1aaSSuzuki K Poulose /*
2655f6fd1aaSSuzuki K Poulose  * etm4x_prohibit_trace - Prohibit the CPU from tracing at all ELs.
2665f6fd1aaSSuzuki K Poulose  * When the CPU supports FEAT_TRF, we could move the ETM to a trace
2675f6fd1aaSSuzuki K Poulose  * prohibited state by filtering the Exception levels via TRFCR_EL1.
2685f6fd1aaSSuzuki K Poulose  */
2695f6fd1aaSSuzuki K Poulose static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
2705f6fd1aaSSuzuki K Poulose {
2715f6fd1aaSSuzuki K Poulose 	/* If the CPU doesn't support FEAT_TRF, nothing to do */
2725f6fd1aaSSuzuki K Poulose 	if (!drvdata->trfcr)
2735f6fd1aaSSuzuki K Poulose 		return;
2745f6fd1aaSSuzuki K Poulose 	cpu_prohibit_trace();
2755f6fd1aaSSuzuki K Poulose }
2765f6fd1aaSSuzuki K Poulose 
2775f6fd1aaSSuzuki K Poulose /*
2785f6fd1aaSSuzuki K Poulose  * etm4x_allow_trace - Allow CPU tracing in the respective ELs,
2795f6fd1aaSSuzuki K Poulose  * as configured by the drvdata->config.mode for the current
2805f6fd1aaSSuzuki K Poulose  * session. Even though we have TRCVICTLR bits to filter the
2815f6fd1aaSSuzuki K Poulose  * trace in the ELs, it doesn't prevent the ETM from generating
2825f6fd1aaSSuzuki K Poulose  * a packet (e.g, TraceInfo) that might contain the addresses from
2835f6fd1aaSSuzuki K Poulose  * the excluded levels. Thus we use the additional controls provided
2845f6fd1aaSSuzuki K Poulose  * via the Trace Filtering controls (FEAT_TRF) to make sure no trace
2855f6fd1aaSSuzuki K Poulose  * is generated for the excluded ELs.
2865f6fd1aaSSuzuki K Poulose  */
2875f6fd1aaSSuzuki K Poulose static void etm4x_allow_trace(struct etmv4_drvdata *drvdata)
2885f6fd1aaSSuzuki K Poulose {
2895f6fd1aaSSuzuki K Poulose 	u64 trfcr = drvdata->trfcr;
2905f6fd1aaSSuzuki K Poulose 
2915f6fd1aaSSuzuki K Poulose 	/* If the CPU doesn't support FEAT_TRF, nothing to do */
2925f6fd1aaSSuzuki K Poulose 	if (!trfcr)
2935f6fd1aaSSuzuki K Poulose 		return;
2945f6fd1aaSSuzuki K Poulose 
2955f6fd1aaSSuzuki K Poulose 	if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
2965f6fd1aaSSuzuki K Poulose 		trfcr &= ~TRFCR_ELx_ExTRE;
2975f6fd1aaSSuzuki K Poulose 	if (drvdata->config.mode & ETM_MODE_EXCL_USER)
2985f6fd1aaSSuzuki K Poulose 		trfcr &= ~TRFCR_ELx_E0TRE;
2995f6fd1aaSSuzuki K Poulose 
3005f6fd1aaSSuzuki K Poulose 	write_trfcr(trfcr);
3015f6fd1aaSSuzuki K Poulose }
3025f6fd1aaSSuzuki K Poulose 
303e7255092SQi Liu #ifdef CONFIG_ETM4X_IMPDEF_FEATURE
304e7255092SQi Liu 
305e7255092SQi Liu #define HISI_HIP08_AMBA_ID		0x000b6d01
306e7255092SQi Liu #define ETM4_AMBA_MASK			0xfffff
307e7255092SQi Liu #define HISI_HIP08_CORE_COMMIT_MASK	0x3000
308e7255092SQi Liu #define HISI_HIP08_CORE_COMMIT_SHIFT	12
309e7255092SQi Liu #define HISI_HIP08_CORE_COMMIT_FULL	0b00
310e7255092SQi Liu #define HISI_HIP08_CORE_COMMIT_LVL_1	0b01
311e7255092SQi Liu #define HISI_HIP08_CORE_COMMIT_REG	sys_reg(3, 1, 15, 2, 5)
312e7255092SQi Liu 
313e7255092SQi Liu struct etm4_arch_features {
314e7255092SQi Liu 	void (*arch_callback)(bool enable);
315e7255092SQi Liu };
316e7255092SQi Liu 
317e7255092SQi Liu static bool etm4_hisi_match_pid(unsigned int id)
318e7255092SQi Liu {
319e7255092SQi Liu 	return (id & ETM4_AMBA_MASK) == HISI_HIP08_AMBA_ID;
320e7255092SQi Liu }
321e7255092SQi Liu 
322e7255092SQi Liu static void etm4_hisi_config_core_commit(bool enable)
323e7255092SQi Liu {
324e7255092SQi Liu 	u8 commit = enable ? HISI_HIP08_CORE_COMMIT_LVL_1 :
325e7255092SQi Liu 		    HISI_HIP08_CORE_COMMIT_FULL;
326e7255092SQi Liu 	u64 val;
327e7255092SQi Liu 
328e7255092SQi Liu 	/*
329e7255092SQi Liu 	 * bit 12 and 13 of HISI_HIP08_CORE_COMMIT_REG are used together
330e7255092SQi Liu 	 * to set core-commit, 2'b00 means cpu is at full speed, 2'b01,
331e7255092SQi Liu 	 * 2'b10, 2'b11 mean reduce pipeline speed, and 2'b01 means level-1
332e7255092SQi Liu 	 * speed(minimun value). So bit 12 and 13 should be cleared together.
333e7255092SQi Liu 	 */
334e7255092SQi Liu 	val = read_sysreg_s(HISI_HIP08_CORE_COMMIT_REG);
335e7255092SQi Liu 	val &= ~HISI_HIP08_CORE_COMMIT_MASK;
336e7255092SQi Liu 	val |= commit << HISI_HIP08_CORE_COMMIT_SHIFT;
337e7255092SQi Liu 	write_sysreg_s(val, HISI_HIP08_CORE_COMMIT_REG);
338e7255092SQi Liu }
339e7255092SQi Liu 
340e7255092SQi Liu static struct etm4_arch_features etm4_features[] = {
341e7255092SQi Liu 	[ETM4_IMPDEF_HISI_CORE_COMMIT] = {
342e7255092SQi Liu 		.arch_callback = etm4_hisi_config_core_commit,
343e7255092SQi Liu 	},
344e7255092SQi Liu 	{},
345e7255092SQi Liu };
346e7255092SQi Liu 
347e7255092SQi Liu static void etm4_enable_arch_specific(struct etmv4_drvdata *drvdata)
348e7255092SQi Liu {
349e7255092SQi Liu 	struct etm4_arch_features *ftr;
350e7255092SQi Liu 	int bit;
351e7255092SQi Liu 
352e7255092SQi Liu 	for_each_set_bit(bit, drvdata->arch_features, ETM4_IMPDEF_FEATURE_MAX) {
353e7255092SQi Liu 		ftr = &etm4_features[bit];
354e7255092SQi Liu 
355e7255092SQi Liu 		if (ftr->arch_callback)
356e7255092SQi Liu 			ftr->arch_callback(true);
357e7255092SQi Liu 	}
358e7255092SQi Liu }
359e7255092SQi Liu 
360e7255092SQi Liu static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
361e7255092SQi Liu {
362e7255092SQi Liu 	struct etm4_arch_features *ftr;
363e7255092SQi Liu 	int bit;
364e7255092SQi Liu 
365e7255092SQi Liu 	for_each_set_bit(bit, drvdata->arch_features, ETM4_IMPDEF_FEATURE_MAX) {
366e7255092SQi Liu 		ftr = &etm4_features[bit];
367e7255092SQi Liu 
368e7255092SQi Liu 		if (ftr->arch_callback)
369e7255092SQi Liu 			ftr->arch_callback(false);
370e7255092SQi Liu 	}
371e7255092SQi Liu }
372e7255092SQi Liu 
373e7255092SQi Liu static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
3745a1c7097SAnshuman Khandual 				     struct csdev_access *csa)
375e7255092SQi Liu {
3765a1c7097SAnshuman Khandual 	/*
3775a1c7097SAnshuman Khandual 	 * TRCPIDR* registers are not required for ETMs with system
3785a1c7097SAnshuman Khandual 	 * instructions. They must be identified by the MIDR+REVIDRs.
3795a1c7097SAnshuman Khandual 	 * Skip the TRCPID checks for now.
3805a1c7097SAnshuman Khandual 	 */
3815a1c7097SAnshuman Khandual 	if (!csa->io_mem)
3825a1c7097SAnshuman Khandual 		return;
3835a1c7097SAnshuman Khandual 
3845a1c7097SAnshuman Khandual 	if (etm4_hisi_match_pid(coresight_get_pid(csa)))
385e7255092SQi Liu 		set_bit(ETM4_IMPDEF_HISI_CORE_COMMIT, drvdata->arch_features);
386e7255092SQi Liu }
387e7255092SQi Liu #else
388e7255092SQi Liu static void etm4_enable_arch_specific(struct etmv4_drvdata *drvdata)
389e7255092SQi Liu {
390e7255092SQi Liu }
391e7255092SQi Liu 
392e7255092SQi Liu static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
393e7255092SQi Liu {
394e7255092SQi Liu }
395e7255092SQi Liu 
396e7255092SQi Liu static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
3975a1c7097SAnshuman Khandual 				     struct csdev_access *csa)
398e7255092SQi Liu {
399e7255092SQi Liu }
400e7255092SQi Liu #endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
401e7255092SQi Liu 
40222a550a3SKim Phillips static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
40322a550a3SKim Phillips {
40422a550a3SKim Phillips 	int i, rc;
40522a550a3SKim Phillips 	struct etmv4_config *config = &drvdata->config;
40602005282SSuzuki K Poulose 	struct coresight_device *csdev = drvdata->csdev;
40702005282SSuzuki K Poulose 	struct device *etm_dev = &csdev->dev;
40802005282SSuzuki K Poulose 	struct csdev_access *csa = &csdev->access;
40922a550a3SKim Phillips 
41033d5573aSSuzuki K Poulose 
41133d5573aSSuzuki K Poulose 	etm4_cs_unlock(drvdata, csa);
412e7255092SQi Liu 	etm4_enable_arch_specific(drvdata);
41322a550a3SKim Phillips 
41422a550a3SKim Phillips 	etm4_os_unlock(drvdata);
41522a550a3SKim Phillips 
4168ce00296SSuzuki K Poulose 	rc = coresight_claim_device_unlocked(csdev);
41722a550a3SKim Phillips 	if (rc)
41822a550a3SKim Phillips 		goto done;
41922a550a3SKim Phillips 
42022a550a3SKim Phillips 	/* Disable the trace unit before programming trace registers */
421f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
42222a550a3SKim Phillips 
4231ab3bb9dSSuzuki K Poulose 	/*
4241ab3bb9dSSuzuki K Poulose 	 * If we use system instructions, we need to synchronize the
4251ab3bb9dSSuzuki K Poulose 	 * write to the TRCPRGCTLR, before accessing the TRCSTATR.
4261ab3bb9dSSuzuki K Poulose 	 * See ARM IHI0064F, section
4271ab3bb9dSSuzuki K Poulose 	 * "4.3.7 Synchronization of register updates"
4281ab3bb9dSSuzuki K Poulose 	 */
4291ab3bb9dSSuzuki K Poulose 	if (!csa->io_mem)
4301ab3bb9dSSuzuki K Poulose 		isb();
4311ab3bb9dSSuzuki K Poulose 
43222a550a3SKim Phillips 	/* wait for TRCSTATR.IDLE to go up */
43302005282SSuzuki K Poulose 	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
43422a550a3SKim Phillips 		dev_err(etm_dev,
43522a550a3SKim Phillips 			"timeout while waiting for Idle Trace Status\n");
4366288b4ceSSuzuki K Poulose 	if (drvdata->nr_pe)
437f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->pe_sel, TRCPROCSELR);
438f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->cfg, TRCCONFIGR);
43922a550a3SKim Phillips 	/* nothing specific implemented */
440f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, 0x0, TRCAUXCTLR);
441f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->eventctrl0, TRCEVENTCTL0R);
442f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->eventctrl1, TRCEVENTCTL1R);
443f7289606SSuzuki K Poulose 	if (drvdata->stallctl)
444f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->stall_ctrl, TRCSTALLCTLR);
445f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->ts_ctrl, TRCTSCTLR);
446f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->syncfreq, TRCSYNCPR);
447f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->ccctlr, TRCCCCTLR);
448f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->bb_ctrl, TRCBBCTLR);
449f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, drvdata->trcid, TRCTRACEIDR);
450f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->vinst_ctrl, TRCVICTLR);
451f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->viiectlr, TRCVIIECTLR);
452f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->vissctlr, TRCVISSCTLR);
45360c519c5SSuzuki K Poulose 	if (drvdata->nr_pe_cmp)
454f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->vipcssctlr, TRCVIPCSSCTLR);
45522a550a3SKim Phillips 	for (i = 0; i < drvdata->nrseqstate - 1; i++)
456f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->seq_ctrl[i], TRCSEQEVRn(i));
457589d9282SJunhao He 	if (drvdata->nrseqstate) {
458f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->seq_rst, TRCSEQRSTEVR);
459f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->seq_state, TRCSEQSTR);
460589d9282SJunhao He 	}
461f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->ext_inp, TRCEXTINSELR);
46222a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_cntr; i++) {
463f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->cntrldvr[i], TRCCNTRLDVRn(i));
464f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->cntr_ctrl[i], TRCCNTCTLRn(i));
465f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->cntr_val[i], TRCCNTVRn(i));
46622a550a3SKim Phillips 	}
46722a550a3SKim Phillips 
46822a550a3SKim Phillips 	/*
46922a550a3SKim Phillips 	 * Resource selector pair 0 is always implemented and reserved.  As
47022a550a3SKim Phillips 	 * such start at 2.
47122a550a3SKim Phillips 	 */
47222a550a3SKim Phillips 	for (i = 2; i < drvdata->nr_resource * 2; i++)
473f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->res_ctrl[i], TRCRSCTLRn(i));
47422a550a3SKim Phillips 
47522a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
47622a550a3SKim Phillips 		/* always clear status bit on restart if using single-shot */
47722a550a3SKim Phillips 		if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
4780544f32bSJames Clark 			config->ss_status[i] &= ~TRCSSCSRn_STATUS;
479f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
480f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
481f6a18f35SSuzuki K Poulose 		if (etm4x_sspcicrn_present(drvdata, i))
482f5bd5236SSuzuki K Poulose 			etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
48322a550a3SKim Phillips 	}
484bf84937eSSteve Clevenger 	for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
485f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i));
486f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i));
48722a550a3SKim Phillips 	}
48822a550a3SKim Phillips 	for (i = 0; i < drvdata->numcidc; i++)
489f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, config->ctxid_pid[i], TRCCIDCVRn(i));
490f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->ctxid_mask0, TRCCIDCCTLR0);
491f2603b22SSuzuki K Poulose 	if (drvdata->numcidc > 4)
492f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->ctxid_mask1, TRCCIDCCTLR1);
49322a550a3SKim Phillips 
49422a550a3SKim Phillips 	for (i = 0; i < drvdata->numvmidc; i++)
495f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, config->vmid_val[i], TRCVMIDCVRn(i));
496f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, config->vmid_mask0, TRCVMIDCCTLR0);
49793dd6440SSuzuki K Poulose 	if (drvdata->numvmidc > 4)
498f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, config->vmid_mask1, TRCVMIDCCTLR1);
49922a550a3SKim Phillips 
50022a550a3SKim Phillips 	if (!drvdata->skip_power_up) {
501f5bd5236SSuzuki K Poulose 		u32 trcpdcr = etm4x_relaxed_read32(csa, TRCPDCR);
502f5bd5236SSuzuki K Poulose 
50322a550a3SKim Phillips 		/*
50422a550a3SKim Phillips 		 * Request to keep the trace unit powered and also
50522a550a3SKim Phillips 		 * emulation of powerdown
50622a550a3SKim Phillips 		 */
507f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
50822a550a3SKim Phillips 	}
50922a550a3SKim Phillips 
51035e1c916SSuzuki K Poulose 	/*
51135e1c916SSuzuki K Poulose 	 * ETE mandates that the TRCRSR is written to before
51235e1c916SSuzuki K Poulose 	 * enabling it.
51335e1c916SSuzuki K Poulose 	 */
51435e1c916SSuzuki K Poulose 	if (etm4x_is_ete(drvdata))
51535e1c916SSuzuki K Poulose 		etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
51635e1c916SSuzuki K Poulose 
5175f6fd1aaSSuzuki K Poulose 	etm4x_allow_trace(drvdata);
51822a550a3SKim Phillips 	/* Enable the trace unit */
519f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
52022a550a3SKim Phillips 
5211ab3bb9dSSuzuki K Poulose 	/* Synchronize the register updates for sysreg access */
5221ab3bb9dSSuzuki K Poulose 	if (!csa->io_mem)
5231ab3bb9dSSuzuki K Poulose 		isb();
5241ab3bb9dSSuzuki K Poulose 
52522a550a3SKim Phillips 	/* wait for TRCSTATR.IDLE to go back down to '0' */
52602005282SSuzuki K Poulose 	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
52722a550a3SKim Phillips 		dev_err(etm_dev,
52822a550a3SKim Phillips 			"timeout while waiting for Idle Trace Status\n");
52922a550a3SKim Phillips 
53022a550a3SKim Phillips 	/*
53122a550a3SKim Phillips 	 * As recommended by section 4.3.7 ("Synchronization when using the
53222a550a3SKim Phillips 	 * memory-mapped interface") of ARM IHI 0064D
53322a550a3SKim Phillips 	 */
53422a550a3SKim Phillips 	dsb(sy);
53522a550a3SKim Phillips 	isb();
53622a550a3SKim Phillips 
53722a550a3SKim Phillips done:
53833d5573aSSuzuki K Poulose 	etm4_cs_lock(drvdata, csa);
53922a550a3SKim Phillips 
54022a550a3SKim Phillips 	dev_dbg(etm_dev, "cpu: %d enable smp call done: %d\n",
54122a550a3SKim Phillips 		drvdata->cpu, rc);
54222a550a3SKim Phillips 	return rc;
54322a550a3SKim Phillips }
54422a550a3SKim Phillips 
54522a550a3SKim Phillips static void etm4_enable_hw_smp_call(void *info)
54622a550a3SKim Phillips {
54722a550a3SKim Phillips 	struct etm4_enable_arg *arg = info;
54822a550a3SKim Phillips 
54922a550a3SKim Phillips 	if (WARN_ON(!arg))
55022a550a3SKim Phillips 		return;
55122a550a3SKim Phillips 	arg->rc = etm4_enable_hw(arg->drvdata);
55222a550a3SKim Phillips }
55322a550a3SKim Phillips 
55422a550a3SKim Phillips /*
55522a550a3SKim Phillips  * The goal of function etm4_config_timestamp_event() is to configure a
55622a550a3SKim Phillips  * counter that will tell the tracer to emit a timestamp packet when it
55722a550a3SKim Phillips  * reaches zero.  This is done in order to get a more fine grained idea
55822a550a3SKim Phillips  * of when instructions are executed so that they can be correlated
55922a550a3SKim Phillips  * with execution on other CPUs.
56022a550a3SKim Phillips  *
56122a550a3SKim Phillips  * To do this the counter itself is configured to self reload and
56222a550a3SKim Phillips  * TRCRSCTLR1 (always true) used to get the counter to decrement.  From
56322a550a3SKim Phillips  * there a resource selector is configured with the counter and the
56422a550a3SKim Phillips  * timestamp control register to use the resource selector to trigger the
56522a550a3SKim Phillips  * event that will insert a timestamp packet in the stream.
56622a550a3SKim Phillips  */
56722a550a3SKim Phillips static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
56822a550a3SKim Phillips {
56922a550a3SKim Phillips 	int ctridx, ret = -EINVAL;
57022a550a3SKim Phillips 	int counter, rselector;
57122a550a3SKim Phillips 	u32 val = 0;
57222a550a3SKim Phillips 	struct etmv4_config *config = &drvdata->config;
57322a550a3SKim Phillips 
57422a550a3SKim Phillips 	/* No point in trying if we don't have at least one counter */
57522a550a3SKim Phillips 	if (!drvdata->nr_cntr)
57622a550a3SKim Phillips 		goto out;
57722a550a3SKim Phillips 
57822a550a3SKim Phillips 	/* Find a counter that hasn't been initialised */
57922a550a3SKim Phillips 	for (ctridx = 0; ctridx < drvdata->nr_cntr; ctridx++)
58022a550a3SKim Phillips 		if (config->cntr_val[ctridx] == 0)
58122a550a3SKim Phillips 			break;
58222a550a3SKim Phillips 
58322a550a3SKim Phillips 	/* All the counters have been configured already, bail out */
58422a550a3SKim Phillips 	if (ctridx == drvdata->nr_cntr) {
58522a550a3SKim Phillips 		pr_debug("%s: no available counter found\n", __func__);
58622a550a3SKim Phillips 		ret = -ENOSPC;
58722a550a3SKim Phillips 		goto out;
58822a550a3SKim Phillips 	}
58922a550a3SKim Phillips 
59022a550a3SKim Phillips 	/*
59122a550a3SKim Phillips 	 * Searching for an available resource selector to use, starting at
59222a550a3SKim Phillips 	 * '2' since every implementation has at least 2 resource selector.
59322a550a3SKim Phillips 	 * ETMIDR4 gives the number of resource selector _pairs_,
59422a550a3SKim Phillips 	 * hence multiply by 2.
59522a550a3SKim Phillips 	 */
59622a550a3SKim Phillips 	for (rselector = 2; rselector < drvdata->nr_resource * 2; rselector++)
59722a550a3SKim Phillips 		if (!config->res_ctrl[rselector])
59822a550a3SKim Phillips 			break;
59922a550a3SKim Phillips 
60022a550a3SKim Phillips 	if (rselector == drvdata->nr_resource * 2) {
60122a550a3SKim Phillips 		pr_debug("%s: no available resource selector found\n",
60222a550a3SKim Phillips 			 __func__);
60322a550a3SKim Phillips 		ret = -ENOSPC;
60422a550a3SKim Phillips 		goto out;
60522a550a3SKim Phillips 	}
60622a550a3SKim Phillips 
60722a550a3SKim Phillips 	/* Remember what counter we used */
60822a550a3SKim Phillips 	counter = 1 << ctridx;
60922a550a3SKim Phillips 
61022a550a3SKim Phillips 	/*
61122a550a3SKim Phillips 	 * Initialise original and reload counter value to the smallest
61222a550a3SKim Phillips 	 * possible value in order to get as much precision as we can.
61322a550a3SKim Phillips 	 */
61422a550a3SKim Phillips 	config->cntr_val[ctridx] = 1;
61522a550a3SKim Phillips 	config->cntrldvr[ctridx] = 1;
61622a550a3SKim Phillips 
61722a550a3SKim Phillips 	/* Set the trace counter control register */
61822a550a3SKim Phillips 	val =  0x1 << 16	|  /* Bit 16, reload counter automatically */
61922a550a3SKim Phillips 	       0x0 << 7		|  /* Select single resource selector */
62022a550a3SKim Phillips 	       0x1;		   /* Resource selector 1, i.e always true */
62122a550a3SKim Phillips 
62222a550a3SKim Phillips 	config->cntr_ctrl[ctridx] = val;
62322a550a3SKim Phillips 
62422a550a3SKim Phillips 	val = 0x2 << 16		| /* Group 0b0010 - Counter and sequencers */
62522a550a3SKim Phillips 	      counter << 0;	  /* Counter to use */
62622a550a3SKim Phillips 
62722a550a3SKim Phillips 	config->res_ctrl[rselector] = val;
62822a550a3SKim Phillips 
62922a550a3SKim Phillips 	val = 0x0 << 7		| /* Select single resource selector */
63022a550a3SKim Phillips 	      rselector;	  /* Resource selector */
63122a550a3SKim Phillips 
63222a550a3SKim Phillips 	config->ts_ctrl = val;
63322a550a3SKim Phillips 
63422a550a3SKim Phillips 	ret = 0;
63522a550a3SKim Phillips out:
63622a550a3SKim Phillips 	return ret;
63722a550a3SKim Phillips }
63822a550a3SKim Phillips 
639810ac401SMike Leach static int etm4_parse_event_config(struct coresight_device *csdev,
64022a550a3SKim Phillips 				   struct perf_event *event)
64122a550a3SKim Phillips {
64222a550a3SKim Phillips 	int ret = 0;
643810ac401SMike Leach 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
64422a550a3SKim Phillips 	struct etmv4_config *config = &drvdata->config;
64522a550a3SKim Phillips 	struct perf_event_attr *attr = &event->attr;
646810ac401SMike Leach 	unsigned long cfg_hash;
64794566c5bSAnshuman Khandual 	int preset, cc_threshold;
64822a550a3SKim Phillips 
64922a550a3SKim Phillips 	/* Clear configuration from previous run */
65022a550a3SKim Phillips 	memset(config, 0, sizeof(struct etmv4_config));
65122a550a3SKim Phillips 
65222a550a3SKim Phillips 	if (attr->exclude_kernel)
65322a550a3SKim Phillips 		config->mode = ETM_MODE_EXCL_KERN;
65422a550a3SKim Phillips 
65522a550a3SKim Phillips 	if (attr->exclude_user)
65622a550a3SKim Phillips 		config->mode = ETM_MODE_EXCL_USER;
65722a550a3SKim Phillips 
65822a550a3SKim Phillips 	/* Always start from the default config */
65922a550a3SKim Phillips 	etm4_set_default_config(config);
66022a550a3SKim Phillips 
66122a550a3SKim Phillips 	/* Configure filters specified on the perf cmd line, if any. */
66222a550a3SKim Phillips 	ret = etm4_set_event_filters(drvdata, event);
66322a550a3SKim Phillips 	if (ret)
66422a550a3SKim Phillips 		goto out;
66522a550a3SKim Phillips 
66622a550a3SKim Phillips 	/* Go from generic option to ETMv4 specifics */
66722a550a3SKim Phillips 	if (attr->config & BIT(ETM_OPT_CYCACC)) {
6681cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_CCI;
66922a550a3SKim Phillips 		/* TRM: Must program this for cycacc to work */
67094566c5bSAnshuman Khandual 		cc_threshold = attr->config3 & ETM_CYC_THRESHOLD_MASK;
67194566c5bSAnshuman Khandual 		if (!cc_threshold)
67294566c5bSAnshuman Khandual 			cc_threshold = ETM_CYC_THRESHOLD_DEFAULT;
67394566c5bSAnshuman Khandual 		if (cc_threshold < drvdata->ccitmin)
67494566c5bSAnshuman Khandual 			cc_threshold = drvdata->ccitmin;
67594566c5bSAnshuman Khandual 		config->ccctlr = cc_threshold;
67622a550a3SKim Phillips 	}
67722a550a3SKim Phillips 	if (attr->config & BIT(ETM_OPT_TS)) {
67822a550a3SKim Phillips 		/*
67922a550a3SKim Phillips 		 * Configure timestamps to be emitted at regular intervals in
68022a550a3SKim Phillips 		 * order to correlate instructions executed on different CPUs
68122a550a3SKim Phillips 		 * (CPU-wide trace scenarios).
68222a550a3SKim Phillips 		 */
68322a550a3SKim Phillips 		ret = etm4_config_timestamp_event(drvdata);
68422a550a3SKim Phillips 
68522a550a3SKim Phillips 		/*
68622a550a3SKim Phillips 		 * No need to go further if timestamp intervals can't
68722a550a3SKim Phillips 		 * be configured.
68822a550a3SKim Phillips 		 */
68922a550a3SKim Phillips 		if (ret)
69022a550a3SKim Phillips 			goto out;
69122a550a3SKim Phillips 
69222a550a3SKim Phillips 		/* bit[11], Global timestamp tracing bit */
6931cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_TS;
69422a550a3SKim Phillips 	}
69522a550a3SKim Phillips 
696aab47386SLeo Yan 	/* Only trace contextID when runs in root PID namespace */
697aab47386SLeo Yan 	if ((attr->config & BIT(ETM_OPT_CTXTID)) &&
698aab47386SLeo Yan 	    task_is_in_init_pid_ns(current))
69922a550a3SKim Phillips 		/* bit[6], Context ID tracing bit */
7001cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_CID;
70122a550a3SKim Phillips 
70288f11864SSuzuki K Poulose 	/*
70388f11864SSuzuki K Poulose 	 * If set bit ETM_OPT_CTXTID2 in perf config, this asks to trace VMID
70488f11864SSuzuki K Poulose 	 * for recording CONTEXTIDR_EL2.  Do not enable VMID tracing if the
70588f11864SSuzuki K Poulose 	 * kernel is not running in EL2.
70688f11864SSuzuki K Poulose 	 */
70788f11864SSuzuki K Poulose 	if (attr->config & BIT(ETM_OPT_CTXTID2)) {
70888f11864SSuzuki K Poulose 		if (!is_kernel_in_hyp_mode()) {
70988f11864SSuzuki K Poulose 			ret = -EINVAL;
71088f11864SSuzuki K Poulose 			goto out;
71188f11864SSuzuki K Poulose 		}
712aab47386SLeo Yan 		/* Only trace virtual contextID when runs in root PID namespace */
713aab47386SLeo Yan 		if (task_is_in_init_pid_ns(current))
7141cf50f64SJames Clark 			config->cfg |= TRCCONFIGR_VMID | TRCCONFIGR_VMIDOPT;
71588f11864SSuzuki K Poulose 	}
71688f11864SSuzuki K Poulose 
71722a550a3SKim Phillips 	/* return stack - enable if selected and supported */
71822a550a3SKim Phillips 	if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack)
71922a550a3SKim Phillips 		/* bit[12], Return stack enable bit */
7201cf50f64SJames Clark 		config->cfg |= TRCCONFIGR_RS;
72122a550a3SKim Phillips 
722810ac401SMike Leach 	/*
723810ac401SMike Leach 	 * Set any selected configuration and preset.
724810ac401SMike Leach 	 *
725810ac401SMike Leach 	 * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
726810ac401SMike Leach 	 * in the perf attributes defined in coresight-etm-perf.c.
727810ac401SMike Leach 	 * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
728810ac401SMike Leach 	 * A zero configid means no configuration active, preset = 0 means no preset selected.
729810ac401SMike Leach 	 */
730810ac401SMike Leach 	if (attr->config2 & GENMASK_ULL(63, 32)) {
731810ac401SMike Leach 		cfg_hash = (u32)(attr->config2 >> 32);
732810ac401SMike Leach 		preset = attr->config & 0xF;
733810ac401SMike Leach 		ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
734810ac401SMike Leach 	}
735810ac401SMike Leach 
7362d693ed4SJames Clark 	/* branch broadcast - enable if selected and supported */
7372d693ed4SJames Clark 	if (attr->config & BIT(ETM_OPT_BRANCH_BROADCAST)) {
7382d693ed4SJames Clark 		if (!drvdata->trcbb) {
7392d693ed4SJames Clark 			/*
7402d693ed4SJames Clark 			 * Missing BB support could cause silent decode errors
7412d693ed4SJames Clark 			 * so fail to open if it's not supported.
7422d693ed4SJames Clark 			 */
7432d693ed4SJames Clark 			ret = -EINVAL;
7442d693ed4SJames Clark 			goto out;
7452d693ed4SJames Clark 		} else {
7462d693ed4SJames Clark 			config->cfg |= BIT(ETM4_CFG_BIT_BB);
7472d693ed4SJames Clark 		}
7482d693ed4SJames Clark 	}
7492d693ed4SJames Clark 
75022a550a3SKim Phillips out:
75122a550a3SKim Phillips 	return ret;
75222a550a3SKim Phillips }
75322a550a3SKim Phillips 
75422a550a3SKim Phillips static int etm4_enable_perf(struct coresight_device *csdev,
75522a550a3SKim Phillips 			    struct perf_event *event)
75622a550a3SKim Phillips {
757df487120SMike Leach 	int ret = 0, trace_id;
75822a550a3SKim Phillips 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
75922a550a3SKim Phillips 
76022a550a3SKim Phillips 	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) {
76122a550a3SKim Phillips 		ret = -EINVAL;
76222a550a3SKim Phillips 		goto out;
76322a550a3SKim Phillips 	}
76422a550a3SKim Phillips 
76522a550a3SKim Phillips 	/* Configure the tracer based on the session's specifics */
766810ac401SMike Leach 	ret = etm4_parse_event_config(csdev, event);
76722a550a3SKim Phillips 	if (ret)
76822a550a3SKim Phillips 		goto out;
769df487120SMike Leach 
770df487120SMike Leach 	/*
771df487120SMike Leach 	 * perf allocates cpu ids as part of _setup_aux() - device needs to use
772df487120SMike Leach 	 * the allocated ID. This reads the current version without allocation.
773df487120SMike Leach 	 *
774df487120SMike Leach 	 * This does not use the trace id lock to prevent lock_dep issues
775df487120SMike Leach 	 * with perf locks - we know the ID cannot change until perf shuts down
776df487120SMike Leach 	 * the session
777df487120SMike Leach 	 */
778df487120SMike Leach 	trace_id = coresight_trace_id_read_cpu_id(drvdata->cpu);
779df487120SMike Leach 	if (!IS_VALID_CS_TRACE_ID(trace_id)) {
780df487120SMike Leach 		dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
781df487120SMike Leach 			dev_name(&drvdata->csdev->dev), drvdata->cpu);
782df487120SMike Leach 		ret = -EINVAL;
783df487120SMike Leach 		goto out;
784df487120SMike Leach 	}
785df487120SMike Leach 	drvdata->trcid = (u8)trace_id;
786df487120SMike Leach 
78722a550a3SKim Phillips 	/* And enable it */
78822a550a3SKim Phillips 	ret = etm4_enable_hw(drvdata);
78922a550a3SKim Phillips 
79022a550a3SKim Phillips out:
79122a550a3SKim Phillips 	return ret;
79222a550a3SKim Phillips }
79322a550a3SKim Phillips 
79422a550a3SKim Phillips static int etm4_enable_sysfs(struct coresight_device *csdev)
79522a550a3SKim Phillips {
79622a550a3SKim Phillips 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
79722a550a3SKim Phillips 	struct etm4_enable_arg arg = { };
7987ebd0ec6SMike Leach 	unsigned long cfg_hash;
7997ebd0ec6SMike Leach 	int ret, preset;
8007ebd0ec6SMike Leach 
8017ebd0ec6SMike Leach 	/* enable any config activated by configfs */
8027ebd0ec6SMike Leach 	cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset);
8037ebd0ec6SMike Leach 	if (cfg_hash) {
8047ebd0ec6SMike Leach 		ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
8057ebd0ec6SMike Leach 		if (ret)
8067ebd0ec6SMike Leach 			return ret;
8077ebd0ec6SMike Leach 	}
80822a550a3SKim Phillips 
80922a550a3SKim Phillips 	spin_lock(&drvdata->spinlock);
81022a550a3SKim Phillips 
811df487120SMike Leach 	/* sysfs needs to read and allocate a trace ID */
812df487120SMike Leach 	ret = etm4_read_alloc_trace_id(drvdata);
813df487120SMike Leach 	if (ret < 0)
814df487120SMike Leach 		goto unlock_sysfs_enable;
815df487120SMike Leach 
81622a550a3SKim Phillips 	/*
81722a550a3SKim Phillips 	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
81822a550a3SKim Phillips 	 * ensures that register writes occur when cpu is powered.
81922a550a3SKim Phillips 	 */
82022a550a3SKim Phillips 	arg.drvdata = drvdata;
82122a550a3SKim Phillips 	ret = smp_call_function_single(drvdata->cpu,
82222a550a3SKim Phillips 				       etm4_enable_hw_smp_call, &arg, 1);
82322a550a3SKim Phillips 	if (!ret)
82422a550a3SKim Phillips 		ret = arg.rc;
82522a550a3SKim Phillips 	if (!ret)
82622a550a3SKim Phillips 		drvdata->sticky_enable = true;
827df487120SMike Leach 
828df487120SMike Leach 	if (ret)
829df487120SMike Leach 		etm4_release_trace_id(drvdata);
830df487120SMike Leach 
831df487120SMike Leach unlock_sysfs_enable:
83222a550a3SKim Phillips 	spin_unlock(&drvdata->spinlock);
83322a550a3SKim Phillips 
83422a550a3SKim Phillips 	if (!ret)
83522a550a3SKim Phillips 		dev_dbg(&csdev->dev, "ETM tracing enabled\n");
83622a550a3SKim Phillips 	return ret;
83722a550a3SKim Phillips }
83822a550a3SKim Phillips 
8399fa36828SJames Clark static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
8409fa36828SJames Clark 		       enum cs_mode mode)
84122a550a3SKim Phillips {
84222a550a3SKim Phillips 	int ret;
84322a550a3SKim Phillips 
844d724f652SJames Clark 	if (!coresight_take_mode(csdev, mode)) {
84522a550a3SKim Phillips 		/* Someone is already using the tracer */
84622a550a3SKim Phillips 		return -EBUSY;
847d724f652SJames Clark 	}
84822a550a3SKim Phillips 
84922a550a3SKim Phillips 	switch (mode) {
85022a550a3SKim Phillips 	case CS_MODE_SYSFS:
85122a550a3SKim Phillips 		ret = etm4_enable_sysfs(csdev);
85222a550a3SKim Phillips 		break;
85322a550a3SKim Phillips 	case CS_MODE_PERF:
85422a550a3SKim Phillips 		ret = etm4_enable_perf(csdev, event);
85522a550a3SKim Phillips 		break;
85622a550a3SKim Phillips 	default:
85722a550a3SKim Phillips 		ret = -EINVAL;
85822a550a3SKim Phillips 	}
85922a550a3SKim Phillips 
86022a550a3SKim Phillips 	/* The tracer didn't start */
86122a550a3SKim Phillips 	if (ret)
862bcaabb95SJames Clark 		coresight_set_mode(csdev, CS_MODE_DISABLED);
86322a550a3SKim Phillips 
86422a550a3SKim Phillips 	return ret;
86522a550a3SKim Phillips }
86622a550a3SKim Phillips 
86722a550a3SKim Phillips static void etm4_disable_hw(void *info)
86822a550a3SKim Phillips {
86922a550a3SKim Phillips 	u32 control;
87022a550a3SKim Phillips 	struct etmv4_drvdata *drvdata = info;
87122a550a3SKim Phillips 	struct etmv4_config *config = &drvdata->config;
87202005282SSuzuki K Poulose 	struct coresight_device *csdev = drvdata->csdev;
87302005282SSuzuki K Poulose 	struct device *etm_dev = &csdev->dev;
87402005282SSuzuki K Poulose 	struct csdev_access *csa = &csdev->access;
87522a550a3SKim Phillips 	int i;
87622a550a3SKim Phillips 
87733d5573aSSuzuki K Poulose 	etm4_cs_unlock(drvdata, csa);
878e7255092SQi Liu 	etm4_disable_arch_specific(drvdata);
87922a550a3SKim Phillips 
88022a550a3SKim Phillips 	if (!drvdata->skip_power_up) {
88122a550a3SKim Phillips 		/* power can be removed from the trace unit now */
882f5bd5236SSuzuki K Poulose 		control = etm4x_relaxed_read32(csa, TRCPDCR);
88322a550a3SKim Phillips 		control &= ~TRCPDCR_PU;
884f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, control, TRCPDCR);
88522a550a3SKim Phillips 	}
88622a550a3SKim Phillips 
887f5bd5236SSuzuki K Poulose 	control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
88822a550a3SKim Phillips 
88922a550a3SKim Phillips 	/* EN, bit[0] Trace unit enable bit */
89022a550a3SKim Phillips 	control &= ~0x1;
89122a550a3SKim Phillips 
89222a550a3SKim Phillips 	/*
8938b481196SSuzuki K Poulose 	 * If the CPU supports v8.4 Trace filter Control,
8948b481196SSuzuki K Poulose 	 * set the ETM to trace prohibited region.
8958b481196SSuzuki K Poulose 	 */
8965f6fd1aaSSuzuki K Poulose 	etm4x_prohibit_trace(drvdata);
8978b481196SSuzuki K Poulose 	/*
89822a550a3SKim Phillips 	 * Make sure everything completes before disabling, as recommended
89922a550a3SKim Phillips 	 * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register,
90022a550a3SKim Phillips 	 * SSTATUS") of ARM IHI 0064D
90122a550a3SKim Phillips 	 */
90222a550a3SKim Phillips 	dsb(sy);
90322a550a3SKim Phillips 	isb();
9048b481196SSuzuki K Poulose 	/* Trace synchronization barrier, is a nop if not supported */
9058b481196SSuzuki K Poulose 	tsb_csync();
906f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
90722a550a3SKim Phillips 
90822a550a3SKim Phillips 	/* wait for TRCSTATR.PMSTABLE to go to '1' */
90902005282SSuzuki K Poulose 	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
91022a550a3SKim Phillips 		dev_err(etm_dev,
91122a550a3SKim Phillips 			"timeout while waiting for PM stable Trace Status\n");
91222a550a3SKim Phillips 	/* read the status of the single shot comparators */
91322a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
91422a550a3SKim Phillips 		config->ss_status[i] =
915f5bd5236SSuzuki K Poulose 			etm4x_relaxed_read32(csa, TRCSSCSRn(i));
91622a550a3SKim Phillips 	}
91722a550a3SKim Phillips 
91822a550a3SKim Phillips 	/* read back the current counter values */
91922a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_cntr; i++) {
92022a550a3SKim Phillips 		config->cntr_val[i] =
921f5bd5236SSuzuki K Poulose 			etm4x_relaxed_read32(csa, TRCCNTVRn(i));
92222a550a3SKim Phillips 	}
92322a550a3SKim Phillips 
9248ce00296SSuzuki K Poulose 	coresight_disclaim_device_unlocked(csdev);
92533d5573aSSuzuki K Poulose 	etm4_cs_lock(drvdata, csa);
92622a550a3SKim Phillips 
92722a550a3SKim Phillips 	dev_dbg(&drvdata->csdev->dev,
92822a550a3SKim Phillips 		"cpu: %d disable smp call done\n", drvdata->cpu);
92922a550a3SKim Phillips }
93022a550a3SKim Phillips 
93122a550a3SKim Phillips static int etm4_disable_perf(struct coresight_device *csdev,
93222a550a3SKim Phillips 			     struct perf_event *event)
93322a550a3SKim Phillips {
93422a550a3SKim Phillips 	u32 control;
93522a550a3SKim Phillips 	struct etm_filters *filters = event->hw.addr_filters;
93622a550a3SKim Phillips 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
937810ac401SMike Leach 	struct perf_event_attr *attr = &event->attr;
93822a550a3SKim Phillips 
93922a550a3SKim Phillips 	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
94022a550a3SKim Phillips 		return -EINVAL;
94122a550a3SKim Phillips 
94222a550a3SKim Phillips 	etm4_disable_hw(drvdata);
943810ac401SMike Leach 	/*
944810ac401SMike Leach 	 * The config_id occupies bits 63:32 of the config2 perf event attr
945810ac401SMike Leach 	 * field. If this is non-zero then we will have enabled a config.
946810ac401SMike Leach 	 */
947810ac401SMike Leach 	if (attr->config2 & GENMASK_ULL(63, 32))
948810ac401SMike Leach 		cscfg_csdev_disable_active_config(csdev);
94922a550a3SKim Phillips 
95022a550a3SKim Phillips 	/*
95122a550a3SKim Phillips 	 * Check if the start/stop logic was active when the unit was stopped.
95222a550a3SKim Phillips 	 * That way we can re-enable the start/stop logic when the process is
95322a550a3SKim Phillips 	 * scheduled again.  Configuration of the start/stop logic happens in
95422a550a3SKim Phillips 	 * function etm4_set_event_filters().
95522a550a3SKim Phillips 	 */
956f5bd5236SSuzuki K Poulose 	control = etm4x_relaxed_read32(&csdev->access, TRCVICTLR);
95722a550a3SKim Phillips 	/* TRCVICTLR::SSSTATUS, bit[9] */
95822a550a3SKim Phillips 	filters->ssstatus = (control & BIT(9));
95922a550a3SKim Phillips 
960df487120SMike Leach 	/*
961df487120SMike Leach 	 * perf will release trace ids when _free_aux() is
962df487120SMike Leach 	 * called at the end of the session.
963df487120SMike Leach 	 */
964df487120SMike Leach 
96522a550a3SKim Phillips 	return 0;
96622a550a3SKim Phillips }
96722a550a3SKim Phillips 
96822a550a3SKim Phillips static void etm4_disable_sysfs(struct coresight_device *csdev)
96922a550a3SKim Phillips {
97022a550a3SKim Phillips 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
97122a550a3SKim Phillips 
97222a550a3SKim Phillips 	/*
97322a550a3SKim Phillips 	 * Taking hotplug lock here protects from clocks getting disabled
97422a550a3SKim Phillips 	 * with tracing being left on (crash scenario) if user disable occurs
97522a550a3SKim Phillips 	 * after cpu online mask indicates the cpu is offline but before the
97622a550a3SKim Phillips 	 * DYING hotplug callback is serviced by the ETM driver.
97722a550a3SKim Phillips 	 */
97822a550a3SKim Phillips 	cpus_read_lock();
97922a550a3SKim Phillips 	spin_lock(&drvdata->spinlock);
98022a550a3SKim Phillips 
98122a550a3SKim Phillips 	/*
98222a550a3SKim Phillips 	 * Executing etm4_disable_hw on the cpu whose ETM is being disabled
98322a550a3SKim Phillips 	 * ensures that register writes occur when cpu is powered.
98422a550a3SKim Phillips 	 */
98522a550a3SKim Phillips 	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
98622a550a3SKim Phillips 
98722a550a3SKim Phillips 	spin_unlock(&drvdata->spinlock);
98822a550a3SKim Phillips 	cpus_read_unlock();
98922a550a3SKim Phillips 
990df487120SMike Leach 	/*
991df487120SMike Leach 	 * we only release trace IDs when resetting sysfs.
992df487120SMike Leach 	 * This permits sysfs users to read the trace ID after the trace
993df487120SMike Leach 	 * session has completed. This maintains operational behaviour with
994df487120SMike Leach 	 * prior trace id allocation method
995df487120SMike Leach 	 */
996df487120SMike Leach 
99722a550a3SKim Phillips 	dev_dbg(&csdev->dev, "ETM tracing disabled\n");
99822a550a3SKim Phillips }
99922a550a3SKim Phillips 
100022a550a3SKim Phillips static void etm4_disable(struct coresight_device *csdev,
100122a550a3SKim Phillips 			 struct perf_event *event)
100222a550a3SKim Phillips {
10039fa36828SJames Clark 	enum cs_mode mode;
100422a550a3SKim Phillips 
100522a550a3SKim Phillips 	/*
100622a550a3SKim Phillips 	 * For as long as the tracer isn't disabled another entity can't
100722a550a3SKim Phillips 	 * change its status.  As such we can read the status here without
100822a550a3SKim Phillips 	 * fearing it will change under us.
100922a550a3SKim Phillips 	 */
1010c95c2733SJames Clark 	mode = coresight_get_mode(csdev);
101122a550a3SKim Phillips 
101222a550a3SKim Phillips 	switch (mode) {
101322a550a3SKim Phillips 	case CS_MODE_DISABLED:
101422a550a3SKim Phillips 		break;
101522a550a3SKim Phillips 	case CS_MODE_SYSFS:
101622a550a3SKim Phillips 		etm4_disable_sysfs(csdev);
101722a550a3SKim Phillips 		break;
101822a550a3SKim Phillips 	case CS_MODE_PERF:
101922a550a3SKim Phillips 		etm4_disable_perf(csdev, event);
102022a550a3SKim Phillips 		break;
102122a550a3SKim Phillips 	}
102222a550a3SKim Phillips 
102322a550a3SKim Phillips 	if (mode)
1024bcaabb95SJames Clark 		coresight_set_mode(csdev, CS_MODE_DISABLED);
102522a550a3SKim Phillips }
102622a550a3SKim Phillips 
102722a550a3SKim Phillips static const struct coresight_ops_source etm4_source_ops = {
102822a550a3SKim Phillips 	.cpu_id		= etm4_cpu_id,
102922a550a3SKim Phillips 	.enable		= etm4_enable,
103022a550a3SKim Phillips 	.disable	= etm4_disable,
103122a550a3SKim Phillips };
103222a550a3SKim Phillips 
103322a550a3SKim Phillips static const struct coresight_ops etm4_cs_ops = {
103422a550a3SKim Phillips 	.source_ops	= &etm4_source_ops,
103522a550a3SKim Phillips };
103622a550a3SKim Phillips 
1037dc1747a7SSuzuki K Poulose static inline bool cpu_supports_sysreg_trace(void)
1038dc1747a7SSuzuki K Poulose {
1039dc1747a7SSuzuki K Poulose 	u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
1040dc1747a7SSuzuki K Poulose 
1041db74cd63SNathan Chancellor 	return ((dfr0 >> ID_AA64DFR0_EL1_TraceVer_SHIFT) & 0xfUL) > 0;
1042dc1747a7SSuzuki K Poulose }
1043dc1747a7SSuzuki K Poulose 
1044dc1747a7SSuzuki K Poulose static bool etm4_init_sysreg_access(struct etmv4_drvdata *drvdata,
1045dc1747a7SSuzuki K Poulose 				    struct csdev_access *csa)
1046dc1747a7SSuzuki K Poulose {
1047dc1747a7SSuzuki K Poulose 	u32 devarch;
1048dc1747a7SSuzuki K Poulose 
1049dc1747a7SSuzuki K Poulose 	if (!cpu_supports_sysreg_trace())
1050dc1747a7SSuzuki K Poulose 		return false;
1051dc1747a7SSuzuki K Poulose 
1052dc1747a7SSuzuki K Poulose 	/*
1053dc1747a7SSuzuki K Poulose 	 * ETMs implementing sysreg access must implement TRCDEVARCH.
1054dc1747a7SSuzuki K Poulose 	 */
1055dc1747a7SSuzuki K Poulose 	devarch = read_etm4x_sysreg_const_offset(TRCDEVARCH);
105635e1c916SSuzuki K Poulose 	switch (devarch & ETM_DEVARCH_ID_MASK) {
105735e1c916SSuzuki K Poulose 	case ETM_DEVARCH_ETMv4x_ARCH:
1058dc1747a7SSuzuki K Poulose 		*csa = (struct csdev_access) {
1059dc1747a7SSuzuki K Poulose 			.io_mem	= false,
1060dc1747a7SSuzuki K Poulose 			.read	= etm4x_sysreg_read,
1061dc1747a7SSuzuki K Poulose 			.write	= etm4x_sysreg_write,
1062dc1747a7SSuzuki K Poulose 		};
106335e1c916SSuzuki K Poulose 		break;
106435e1c916SSuzuki K Poulose 	case ETM_DEVARCH_ETE_ARCH:
106535e1c916SSuzuki K Poulose 		*csa = (struct csdev_access) {
106635e1c916SSuzuki K Poulose 			.io_mem	= false,
106735e1c916SSuzuki K Poulose 			.read	= ete_sysreg_read,
106835e1c916SSuzuki K Poulose 			.write	= ete_sysreg_write,
106935e1c916SSuzuki K Poulose 		};
107035e1c916SSuzuki K Poulose 		break;
107135e1c916SSuzuki K Poulose 	default:
107235e1c916SSuzuki K Poulose 		return false;
107335e1c916SSuzuki K Poulose 	}
1074dc1747a7SSuzuki K Poulose 
1075dc1747a7SSuzuki K Poulose 	drvdata->arch = etm_devarch_to_arch(devarch);
1076dc1747a7SSuzuki K Poulose 	return true;
1077dc1747a7SSuzuki K Poulose }
1078dc1747a7SSuzuki K Poulose 
107973d779a0SAnshuman Khandual static bool is_devtype_cpu_trace(void __iomem *base)
108073d779a0SAnshuman Khandual {
108173d779a0SAnshuman Khandual 	u32 devtype = readl(base + TRCDEVTYPE);
108273d779a0SAnshuman Khandual 
108373d779a0SAnshuman Khandual 	return (devtype == CS_DEVTYPE_PE_TRACE);
108473d779a0SAnshuman Khandual }
108573d779a0SAnshuman Khandual 
1086fd6e7905SSuzuki K Poulose static bool etm4_init_iomem_access(struct etmv4_drvdata *drvdata,
1087fd6e7905SSuzuki K Poulose 				   struct csdev_access *csa)
1088fd6e7905SSuzuki K Poulose {
10898b94db1eSSuzuki K Poulose 	u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
10908b94db1eSSuzuki K Poulose 
109173d779a0SAnshuman Khandual 	if (!is_coresight_device(drvdata->base) || !is_devtype_cpu_trace(drvdata->base))
109273d779a0SAnshuman Khandual 		return false;
109373d779a0SAnshuman Khandual 
10948b94db1eSSuzuki K Poulose 	/*
10958b94db1eSSuzuki K Poulose 	 * All ETMs must implement TRCDEVARCH to indicate that
1096735e7b30SSuzuki K Poulose 	 * the component is an ETMv4. Even though TRCIDR1 also
1097735e7b30SSuzuki K Poulose 	 * contains the information, it is part of the "Trace"
1098735e7b30SSuzuki K Poulose 	 * register and must be accessed with the OSLK cleared,
1099735e7b30SSuzuki K Poulose 	 * with MMIO. But we cannot touch the OSLK until we are
1100735e7b30SSuzuki K Poulose 	 * sure this is an ETM. So rely only on the TRCDEVARCH.
11018b94db1eSSuzuki K Poulose 	 */
1102735e7b30SSuzuki K Poulose 	if ((devarch & ETM_DEVARCH_ID_MASK) != ETM_DEVARCH_ETMv4x_ARCH) {
1103735e7b30SSuzuki K Poulose 		pr_warn_once("TRCDEVARCH doesn't match ETMv4 architecture\n");
11048b94db1eSSuzuki K Poulose 		return false;
11058b94db1eSSuzuki K Poulose 	}
11068b94db1eSSuzuki K Poulose 
1107735e7b30SSuzuki K Poulose 	drvdata->arch = etm_devarch_to_arch(devarch);
1108fd6e7905SSuzuki K Poulose 	*csa = CSDEV_ACCESS_IOMEM(drvdata->base);
1109fd6e7905SSuzuki K Poulose 	return true;
1110fd6e7905SSuzuki K Poulose }
1111fd6e7905SSuzuki K Poulose 
1112fd6e7905SSuzuki K Poulose static bool etm4_init_csdev_access(struct etmv4_drvdata *drvdata,
1113fd6e7905SSuzuki K Poulose 				   struct csdev_access *csa)
1114fd6e7905SSuzuki K Poulose {
1115dc1747a7SSuzuki K Poulose 	/*
1116dc1747a7SSuzuki K Poulose 	 * Always choose the memory mapped io, if there is
1117dc1747a7SSuzuki K Poulose 	 * a memory map to prevent sysreg access on broken
1118dc1747a7SSuzuki K Poulose 	 * systems.
1119dc1747a7SSuzuki K Poulose 	 */
1120fd6e7905SSuzuki K Poulose 	if (drvdata->base)
1121fd6e7905SSuzuki K Poulose 		return etm4_init_iomem_access(drvdata, csa);
1122fd6e7905SSuzuki K Poulose 
1123dc1747a7SSuzuki K Poulose 	if (etm4_init_sysreg_access(drvdata, csa))
1124dc1747a7SSuzuki K Poulose 		return true;
1125dc1747a7SSuzuki K Poulose 
1126fd6e7905SSuzuki K Poulose 	return false;
1127fd6e7905SSuzuki K Poulose }
1128fd6e7905SSuzuki K Poulose 
11295f6fd1aaSSuzuki K Poulose static void cpu_detect_trace_filtering(struct etmv4_drvdata *drvdata)
1130e5d51fbeSJonathan Zhou {
1131e5d51fbeSJonathan Zhou 	u64 dfr0 = read_sysreg(id_aa64dfr0_el1);
1132e5d51fbeSJonathan Zhou 	u64 trfcr;
1133e5d51fbeSJonathan Zhou 
11345f6fd1aaSSuzuki K Poulose 	drvdata->trfcr = 0;
1135db74cd63SNathan Chancellor 	if (!cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT))
1136e5d51fbeSJonathan Zhou 		return;
1137e5d51fbeSJonathan Zhou 
1138e5d51fbeSJonathan Zhou 	/*
1139e5d51fbeSJonathan Zhou 	 * If the CPU supports v8.4 SelfHosted Tracing, enable
1140e5d51fbeSJonathan Zhou 	 * tracing at the kernel EL and EL0, forcing to use the
1141e5d51fbeSJonathan Zhou 	 * virtual time as the timestamp.
1142e5d51fbeSJonathan Zhou 	 */
1143e5d51fbeSJonathan Zhou 	trfcr = (TRFCR_ELx_TS_VIRTUAL |
1144e5d51fbeSJonathan Zhou 		 TRFCR_ELx_ExTRE |
1145e5d51fbeSJonathan Zhou 		 TRFCR_ELx_E0TRE);
1146e5d51fbeSJonathan Zhou 
1147e5d51fbeSJonathan Zhou 	/* If we are running at EL2, allow tracing the CONTEXTIDR_EL2. */
1148e5d51fbeSJonathan Zhou 	if (is_kernel_in_hyp_mode())
1149e5d51fbeSJonathan Zhou 		trfcr |= TRFCR_EL2_CX;
1150e5d51fbeSJonathan Zhou 
11515f6fd1aaSSuzuki K Poulose 	drvdata->trfcr = trfcr;
1152e5d51fbeSJonathan Zhou }
1153e5d51fbeSJonathan Zhou 
11544aff040bSAnshuman Khandual /*
11554aff040bSAnshuman Khandual  * The following errata on applicable cpu ranges, affect the CCITMIN filed
11564aff040bSAnshuman Khandual  * in TCRIDR3 register. Software read for the field returns 0x100 limiting
11574aff040bSAnshuman Khandual  * the cycle threshold granularity, whereas the right value should have
11584aff040bSAnshuman Khandual  * been 0x4, which is well supported in the hardware.
11594aff040bSAnshuman Khandual  */
11604aff040bSAnshuman Khandual static struct midr_range etm_wrong_ccitmin_cpus[] = {
11614aff040bSAnshuman Khandual 	/* Erratum #1490853 - Cortex-A76 */
11624aff040bSAnshuman Khandual 	MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 4, 0),
11634aff040bSAnshuman Khandual 	/* Erratum #1490853 - Neoverse-N1 */
11644aff040bSAnshuman Khandual 	MIDR_RANGE(MIDR_NEOVERSE_N1, 0, 0, 4, 0),
11654aff040bSAnshuman Khandual 	/* Erratum #1491015 - Cortex-A77 */
11664aff040bSAnshuman Khandual 	MIDR_RANGE(MIDR_CORTEX_A77, 0, 0, 1, 0),
11674aff040bSAnshuman Khandual 	/* Erratum #1502854 - Cortex-X1 */
11684aff040bSAnshuman Khandual 	MIDR_REV(MIDR_CORTEX_X1, 0, 0),
11694aff040bSAnshuman Khandual 	/* Erratum #1619801 - Neoverse-V1 */
11704aff040bSAnshuman Khandual 	MIDR_REV(MIDR_NEOVERSE_V1, 0, 0),
11714aff040bSAnshuman Khandual 	{},
11724aff040bSAnshuman Khandual };
11734aff040bSAnshuman Khandual 
11744aff040bSAnshuman Khandual static void etm4_fixup_wrong_ccitmin(struct etmv4_drvdata *drvdata)
11754aff040bSAnshuman Khandual {
11764aff040bSAnshuman Khandual 	/*
11774aff040bSAnshuman Khandual 	 * Erratum affected cpus will read 256 as the minimum
11784aff040bSAnshuman Khandual 	 * instruction trace cycle counting threshold whereas
11794aff040bSAnshuman Khandual 	 * the correct value should be 4 instead. Override the
11804aff040bSAnshuman Khandual 	 * recorded value for 'drvdata->ccitmin' to workaround
11814aff040bSAnshuman Khandual 	 * this problem.
11824aff040bSAnshuman Khandual 	 */
11834aff040bSAnshuman Khandual 	if (is_midr_in_range_list(read_cpuid_id(), etm_wrong_ccitmin_cpus)) {
11844aff040bSAnshuman Khandual 		if (drvdata->ccitmin == 256)
11854aff040bSAnshuman Khandual 			drvdata->ccitmin = 4;
11864aff040bSAnshuman Khandual 	}
11874aff040bSAnshuman Khandual }
11884aff040bSAnshuman Khandual 
118922a550a3SKim Phillips static void etm4_init_arch_data(void *info)
119022a550a3SKim Phillips {
119122a550a3SKim Phillips 	u32 etmidr0;
119222a550a3SKim Phillips 	u32 etmidr2;
119322a550a3SKim Phillips 	u32 etmidr3;
119422a550a3SKim Phillips 	u32 etmidr4;
119522a550a3SKim Phillips 	u32 etmidr5;
1196fd6e7905SSuzuki K Poulose 	struct etm4_init_arg *init_arg = info;
1197fd6e7905SSuzuki K Poulose 	struct etmv4_drvdata *drvdata;
1198fd6e7905SSuzuki K Poulose 	struct csdev_access *csa;
11991bbe0a24SMao Jinlong 	struct device *dev = init_arg->dev;
120022a550a3SKim Phillips 	int i;
120122a550a3SKim Phillips 
12023c728e07STamas Zsoldos 	drvdata = dev_get_drvdata(init_arg->dev);
1203fd6e7905SSuzuki K Poulose 	csa = init_arg->csa;
1204fd6e7905SSuzuki K Poulose 
1205fd6e7905SSuzuki K Poulose 	/*
1206fd6e7905SSuzuki K Poulose 	 * If we are unable to detect the access mechanism,
1207fd6e7905SSuzuki K Poulose 	 * or unable to detect the trace unit type, fail
1208fd6e7905SSuzuki K Poulose 	 * early.
1209fd6e7905SSuzuki K Poulose 	 */
1210fd6e7905SSuzuki K Poulose 	if (!etm4_init_csdev_access(drvdata, csa))
1211fd6e7905SSuzuki K Poulose 		return;
1212fd6e7905SSuzuki K Poulose 
12131bbe0a24SMao Jinlong 	if (!csa->io_mem ||
12141bbe0a24SMao Jinlong 	    fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
12151bbe0a24SMao Jinlong 		drvdata->skip_power_up = true;
12161bbe0a24SMao Jinlong 
1217bc2c689fSSuzuki K Poulose 	/* Detect the support for OS Lock before we actually use it */
1218bc2c689fSSuzuki K Poulose 	etm_detect_os_lock(drvdata, csa);
1219bc2c689fSSuzuki K Poulose 
122022a550a3SKim Phillips 	/* Make sure all registers are accessible */
1221f5bd5236SSuzuki K Poulose 	etm4_os_unlock_csa(drvdata, csa);
122233d5573aSSuzuki K Poulose 	etm4_cs_unlock(drvdata, csa);
122322a550a3SKim Phillips 
12245a1c7097SAnshuman Khandual 	etm4_check_arch_features(drvdata, csa);
1225e97db2cfSSuzuki K Poulose 
122622a550a3SKim Phillips 	/* find all capabilities of the tracing unit */
1227f5bd5236SSuzuki K Poulose 	etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);
122822a550a3SKim Phillips 
122922a550a3SKim Phillips 	/* INSTP0, bits[2:1] P0 tracing support field */
1230e601cc9aSJames Clark 	drvdata->instrp0 = !!(FIELD_GET(TRCIDR0_INSTP0_MASK, etmidr0) == 0b11);
123122a550a3SKim Phillips 	/* TRCBB, bit[5] Branch broadcast tracing support bit */
1232e601cc9aSJames Clark 	drvdata->trcbb = !!(etmidr0 & TRCIDR0_TRCBB);
123322a550a3SKim Phillips 	/* TRCCOND, bit[6] Conditional instruction tracing support bit */
1234e601cc9aSJames Clark 	drvdata->trccond = !!(etmidr0 & TRCIDR0_TRCCOND);
123522a550a3SKim Phillips 	/* TRCCCI, bit[7] Cycle counting instruction bit */
1236e601cc9aSJames Clark 	drvdata->trccci = !!(etmidr0 & TRCIDR0_TRCCCI);
123722a550a3SKim Phillips 	/* RETSTACK, bit[9] Return stack bit */
1238e601cc9aSJames Clark 	drvdata->retstack = !!(etmidr0 & TRCIDR0_RETSTACK);
123922a550a3SKim Phillips 	/* NUMEVENT, bits[11:10] Number of events field */
1240e601cc9aSJames Clark 	drvdata->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0);
124122a550a3SKim Phillips 	/* QSUPP, bits[16:15] Q element support field */
1242e601cc9aSJames Clark 	drvdata->q_support = FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0);
124346bf8d7cSSuzuki K Poulose 	if (drvdata->q_support)
124446bf8d7cSSuzuki K Poulose 		drvdata->q_filt = !!(etmidr0 & TRCIDR0_QFILT);
124522a550a3SKim Phillips 	/* TSSIZE, bits[28:24] Global timestamp size field */
1246e601cc9aSJames Clark 	drvdata->ts_size = FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0);
124722a550a3SKim Phillips 
124822a550a3SKim Phillips 	/* maximum size of resources */
1249f5bd5236SSuzuki K Poulose 	etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
125022a550a3SKim Phillips 	/* CIDSIZE, bits[9:5] Indicates the Context ID size */
1251cf0c7f18SJames Clark 	drvdata->ctxid_size = FIELD_GET(TRCIDR2_CIDSIZE_MASK, etmidr2);
125222a550a3SKim Phillips 	/* VMIDSIZE, bits[14:10] Indicates the VMID size */
1253cf0c7f18SJames Clark 	drvdata->vmid_size = FIELD_GET(TRCIDR2_VMIDSIZE_MASK, etmidr2);
125422a550a3SKim Phillips 	/* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */
1255cf0c7f18SJames Clark 	drvdata->ccsize = FIELD_GET(TRCIDR2_CCSIZE_MASK, etmidr2);
125622a550a3SKim Phillips 
1257f5bd5236SSuzuki K Poulose 	etmidr3 = etm4x_relaxed_read32(csa, TRCIDR3);
125822a550a3SKim Phillips 	/* CCITMIN, bits[11:0] minimum threshold value that can be programmed */
1259f4d1f214SJames Clark 	drvdata->ccitmin = FIELD_GET(TRCIDR3_CCITMIN_MASK, etmidr3);
12604aff040bSAnshuman Khandual 	etm4_fixup_wrong_ccitmin(drvdata);
12614aff040bSAnshuman Khandual 
126222a550a3SKim Phillips 	/* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
1263f4d1f214SJames Clark 	drvdata->s_ex_level = FIELD_GET(TRCIDR3_EXLEVEL_S_MASK, etmidr3);
12641d3eead7SSuzuki K Poulose 	drvdata->config.s_ex_level = drvdata->s_ex_level;
126522a550a3SKim Phillips 	/* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */
1266f4d1f214SJames Clark 	drvdata->ns_ex_level = FIELD_GET(TRCIDR3_EXLEVEL_NS_MASK, etmidr3);
126722a550a3SKim Phillips 	/*
126822a550a3SKim Phillips 	 * TRCERR, bit[24] whether a trace unit can trace a
126922a550a3SKim Phillips 	 * system error exception.
127022a550a3SKim Phillips 	 */
1271f4d1f214SJames Clark 	drvdata->trc_error = !!(etmidr3 & TRCIDR3_TRCERR);
127222a550a3SKim Phillips 	/* SYNCPR, bit[25] implementation has a fixed synchronization period? */
1273f4d1f214SJames Clark 	drvdata->syncpr = !!(etmidr3 & TRCIDR3_SYNCPR);
127422a550a3SKim Phillips 	/* STALLCTL, bit[26] is stall control implemented? */
1275f4d1f214SJames Clark 	drvdata->stallctl = !!(etmidr3 & TRCIDR3_STALLCTL);
127622a550a3SKim Phillips 	/* SYSSTALL, bit[27] implementation can support stall control? */
1277f4d1f214SJames Clark 	drvdata->sysstall = !!(etmidr3 & TRCIDR3_SYSSTALL);
12784e218727SSuzuki K Poulose 	/*
12794e218727SSuzuki K Poulose 	 * NUMPROC - the number of PEs available for tracing, 5bits
12804e218727SSuzuki K Poulose 	 *         = TRCIDR3.bits[13:12]bits[30:28]
12814e218727SSuzuki K Poulose 	 *  bits[4:3] = TRCIDR3.bits[13:12] (since etm-v4.2, otherwise RES0)
12824e218727SSuzuki K Poulose 	 *  bits[3:0] = TRCIDR3.bits[30:28]
12834e218727SSuzuki K Poulose 	 */
1284f4d1f214SJames Clark 	drvdata->nr_pe =  (FIELD_GET(TRCIDR3_NUMPROC_HI_MASK, etmidr3) << 3) |
1285f4d1f214SJames Clark 			   FIELD_GET(TRCIDR3_NUMPROC_LO_MASK, etmidr3);
128622a550a3SKim Phillips 	/* NOOVERFLOW, bit[31] is trace overflow prevention supported */
1287f4d1f214SJames Clark 	drvdata->nooverflow = !!(etmidr3 & TRCIDR3_NOOVERFLOW);
128822a550a3SKim Phillips 
128922a550a3SKim Phillips 	/* number of resources trace unit supports */
1290f5bd5236SSuzuki K Poulose 	etmidr4 = etm4x_relaxed_read32(csa, TRCIDR4);
129122a550a3SKim Phillips 	/* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */
1292ea69dbb8SJames Clark 	drvdata->nr_addr_cmp = FIELD_GET(TRCIDR4_NUMACPAIRS_MASK, etmidr4);
129322a550a3SKim Phillips 	/* NUMPC, bits[15:12] number of PE comparator inputs for tracing */
1294ea69dbb8SJames Clark 	drvdata->nr_pe_cmp = FIELD_GET(TRCIDR4_NUMPC_MASK, etmidr4);
129522a550a3SKim Phillips 	/*
129622a550a3SKim Phillips 	 * NUMRSPAIR, bits[19:16]
129722a550a3SKim Phillips 	 * The number of resource pairs conveyed by the HW starts at 0, i.e a
129822a550a3SKim Phillips 	 * value of 0x0 indicate 1 resource pair, 0x1 indicate two and so on.
129922a550a3SKim Phillips 	 * As such add 1 to the value of NUMRSPAIR for a better representation.
130022a550a3SKim Phillips 	 *
130122a550a3SKim Phillips 	 * For ETM v4.3 and later, 0x0 means 0, and no pairs are available -
130222a550a3SKim Phillips 	 * the default TRUE and FALSE resource selectors are omitted.
130322a550a3SKim Phillips 	 * Otherwise for values 0x1 and above the number is N + 1 as per v4.2.
130422a550a3SKim Phillips 	 */
1305ea69dbb8SJames Clark 	drvdata->nr_resource = FIELD_GET(TRCIDR4_NUMRSPAIR_MASK, etmidr4);
1306e49516e2SSuzuki K Poulose 	if ((drvdata->arch < ETM_ARCH_V4_3) || (drvdata->nr_resource > 0))
130722a550a3SKim Phillips 		drvdata->nr_resource += 1;
130822a550a3SKim Phillips 	/*
130922a550a3SKim Phillips 	 * NUMSSCC, bits[23:20] the number of single-shot
131022a550a3SKim Phillips 	 * comparator control for tracing. Read any status regs as these
131122a550a3SKim Phillips 	 * also contain RO capability data.
131222a550a3SKim Phillips 	 */
1313ea69dbb8SJames Clark 	drvdata->nr_ss_cmp = FIELD_GET(TRCIDR4_NUMSSCC_MASK, etmidr4);
131422a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
131522a550a3SKim Phillips 		drvdata->config.ss_status[i] =
1316f5bd5236SSuzuki K Poulose 			etm4x_relaxed_read32(csa, TRCSSCSRn(i));
131722a550a3SKim Phillips 	}
131822a550a3SKim Phillips 	/* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */
1319ea69dbb8SJames Clark 	drvdata->numcidc = FIELD_GET(TRCIDR4_NUMCIDC_MASK, etmidr4);
132022a550a3SKim Phillips 	/* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */
1321ea69dbb8SJames Clark 	drvdata->numvmidc = FIELD_GET(TRCIDR4_NUMVMIDC_MASK, etmidr4);
132222a550a3SKim Phillips 
1323f5bd5236SSuzuki K Poulose 	etmidr5 = etm4x_relaxed_read32(csa, TRCIDR5);
132422a550a3SKim Phillips 	/* NUMEXTIN, bits[8:0] number of external inputs implemented */
1325028e5460SJames Clark 	drvdata->nr_ext_inp = FIELD_GET(TRCIDR5_NUMEXTIN_MASK, etmidr5);
132622a550a3SKim Phillips 	/* TRACEIDSIZE, bits[21:16] indicates the trace ID width */
1327028e5460SJames Clark 	drvdata->trcid_size = FIELD_GET(TRCIDR5_TRACEIDSIZE_MASK, etmidr5);
132822a550a3SKim Phillips 	/* ATBTRIG, bit[22] implementation can support ATB triggers? */
1329028e5460SJames Clark 	drvdata->atbtrig = !!(etmidr5 & TRCIDR5_ATBTRIG);
133022a550a3SKim Phillips 	/*
133122a550a3SKim Phillips 	 * LPOVERRIDE, bit[23] implementation supports
133222a550a3SKim Phillips 	 * low-power state override
133322a550a3SKim Phillips 	 */
1334028e5460SJames Clark 	drvdata->lpoverride = (etmidr5 & TRCIDR5_LPOVERRIDE) && (!drvdata->skip_power_up);
133522a550a3SKim Phillips 	/* NUMSEQSTATE, bits[27:25] number of sequencer states implemented */
1336028e5460SJames Clark 	drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
133722a550a3SKim Phillips 	/* NUMCNTR, bits[30:28] number of counters available for tracing */
1338028e5460SJames Clark 	drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
133933d5573aSSuzuki K Poulose 	etm4_cs_lock(drvdata, csa);
13405f6fd1aaSSuzuki K Poulose 	cpu_detect_trace_filtering(drvdata);
134122a550a3SKim Phillips }
134222a550a3SKim Phillips 
13434d1b1fd7SSuzuki K Poulose static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
13444d1b1fd7SSuzuki K Poulose {
13456ba7f2bcSJames Clark 	return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
13464d1b1fd7SSuzuki K Poulose }
13474d1b1fd7SSuzuki K Poulose 
134822a550a3SKim Phillips /* Set ELx trace filter access in the TRCVICTLR register */
134922a550a3SKim Phillips static void etm4_set_victlr_access(struct etmv4_config *config)
135022a550a3SKim Phillips {
13514d1b1fd7SSuzuki K Poulose 	config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_MASK;
13524d1b1fd7SSuzuki K Poulose 	config->vinst_ctrl |= etm4_get_victlr_access_type(config);
135322a550a3SKim Phillips }
135422a550a3SKim Phillips 
135522a550a3SKim Phillips static void etm4_set_default_config(struct etmv4_config *config)
135622a550a3SKim Phillips {
135722a550a3SKim Phillips 	/* disable all events tracing */
135822a550a3SKim Phillips 	config->eventctrl0 = 0x0;
135922a550a3SKim Phillips 	config->eventctrl1 = 0x0;
136022a550a3SKim Phillips 
136122a550a3SKim Phillips 	/* disable stalling */
136222a550a3SKim Phillips 	config->stall_ctrl = 0x0;
136322a550a3SKim Phillips 
136422a550a3SKim Phillips 	/* enable trace synchronization every 4096 bytes, if available */
136522a550a3SKim Phillips 	config->syncfreq = 0xC;
136622a550a3SKim Phillips 
136722a550a3SKim Phillips 	/* disable timestamp event */
136822a550a3SKim Phillips 	config->ts_ctrl = 0x0;
136922a550a3SKim Phillips 
137022a550a3SKim Phillips 	/* TRCVICTLR::EVENT = 0x01, select the always on logic */
13716ba7f2bcSJames Clark 	config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
137222a550a3SKim Phillips 
137322a550a3SKim Phillips 	/* TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering */
137422a550a3SKim Phillips 	etm4_set_victlr_access(config);
137522a550a3SKim Phillips }
137622a550a3SKim Phillips 
137722a550a3SKim Phillips static u64 etm4_get_ns_access_type(struct etmv4_config *config)
137822a550a3SKim Phillips {
137922a550a3SKim Phillips 	u64 access_type = 0;
138022a550a3SKim Phillips 
138122a550a3SKim Phillips 	/*
13824d1b1fd7SSuzuki K Poulose 	 * EXLEVEL_NS, for NonSecure Exception levels.
13834d1b1fd7SSuzuki K Poulose 	 * The mask here is a generic value and must be
13844d1b1fd7SSuzuki K Poulose 	 * shifted to the corresponding field for the registers
138522a550a3SKim Phillips 	 */
138622a550a3SKim Phillips 	if (!is_kernel_in_hyp_mode()) {
138722a550a3SKim Phillips 		/* Stay away from hypervisor mode for non-VHE */
138822a550a3SKim Phillips 		access_type =  ETM_EXLEVEL_NS_HYP;
138922a550a3SKim Phillips 		if (config->mode & ETM_MODE_EXCL_KERN)
139022a550a3SKim Phillips 			access_type |= ETM_EXLEVEL_NS_OS;
139122a550a3SKim Phillips 	} else if (config->mode & ETM_MODE_EXCL_KERN) {
139222a550a3SKim Phillips 		access_type = ETM_EXLEVEL_NS_HYP;
139322a550a3SKim Phillips 	}
139422a550a3SKim Phillips 
139522a550a3SKim Phillips 	if (config->mode & ETM_MODE_EXCL_USER)
139622a550a3SKim Phillips 		access_type |= ETM_EXLEVEL_NS_APP;
139722a550a3SKim Phillips 
139822a550a3SKim Phillips 	return access_type;
139922a550a3SKim Phillips }
140022a550a3SKim Phillips 
14014d1b1fd7SSuzuki K Poulose /*
14024d1b1fd7SSuzuki K Poulose  * Construct the exception level masks for a given config.
14034d1b1fd7SSuzuki K Poulose  * This must be shifted to the corresponding register field
14044d1b1fd7SSuzuki K Poulose  * for usage.
14054d1b1fd7SSuzuki K Poulose  */
140622a550a3SKim Phillips static u64 etm4_get_access_type(struct etmv4_config *config)
140722a550a3SKim Phillips {
14084d1b1fd7SSuzuki K Poulose 	/* All Secure exception levels are excluded from the trace */
14094d1b1fd7SSuzuki K Poulose 	return etm4_get_ns_access_type(config) | (u64)config->s_ex_level;
14104d1b1fd7SSuzuki K Poulose }
141122a550a3SKim Phillips 
14124d1b1fd7SSuzuki K Poulose static u64 etm4_get_comparator_access_type(struct etmv4_config *config)
14134d1b1fd7SSuzuki K Poulose {
14144d1b1fd7SSuzuki K Poulose 	return etm4_get_access_type(config) << TRCACATR_EXLEVEL_SHIFT;
141522a550a3SKim Phillips }
141622a550a3SKim Phillips 
141722a550a3SKim Phillips static void etm4_set_comparator_filter(struct etmv4_config *config,
141822a550a3SKim Phillips 				       u64 start, u64 stop, int comparator)
141922a550a3SKim Phillips {
14204d1b1fd7SSuzuki K Poulose 	u64 access_type = etm4_get_comparator_access_type(config);
142122a550a3SKim Phillips 
142222a550a3SKim Phillips 	/* First half of default address comparator */
142322a550a3SKim Phillips 	config->addr_val[comparator] = start;
142422a550a3SKim Phillips 	config->addr_acc[comparator] = access_type;
142522a550a3SKim Phillips 	config->addr_type[comparator] = ETM_ADDR_TYPE_RANGE;
142622a550a3SKim Phillips 
142722a550a3SKim Phillips 	/* Second half of default address comparator */
142822a550a3SKim Phillips 	config->addr_val[comparator + 1] = stop;
142922a550a3SKim Phillips 	config->addr_acc[comparator + 1] = access_type;
143022a550a3SKim Phillips 	config->addr_type[comparator + 1] = ETM_ADDR_TYPE_RANGE;
143122a550a3SKim Phillips 
143222a550a3SKim Phillips 	/*
143322a550a3SKim Phillips 	 * Configure the ViewInst function to include this address range
143422a550a3SKim Phillips 	 * comparator.
143522a550a3SKim Phillips 	 *
143622a550a3SKim Phillips 	 * @comparator is divided by two since it is the index in the
143722a550a3SKim Phillips 	 * etmv4_config::addr_val array but register TRCVIIECTLR deals with
143822a550a3SKim Phillips 	 * address range comparator _pairs_.
143922a550a3SKim Phillips 	 *
144022a550a3SKim Phillips 	 * Therefore:
144122a550a3SKim Phillips 	 *	index 0 -> compatator pair 0
144222a550a3SKim Phillips 	 *	index 2 -> comparator pair 1
144322a550a3SKim Phillips 	 *	index 4 -> comparator pair 2
144422a550a3SKim Phillips 	 *	...
144522a550a3SKim Phillips 	 *	index 14 -> comparator pair 7
144622a550a3SKim Phillips 	 */
144722a550a3SKim Phillips 	config->viiectlr |= BIT(comparator / 2);
144822a550a3SKim Phillips }
144922a550a3SKim Phillips 
145022a550a3SKim Phillips static void etm4_set_start_stop_filter(struct etmv4_config *config,
145122a550a3SKim Phillips 				       u64 address, int comparator,
145222a550a3SKim Phillips 				       enum etm_addr_type type)
145322a550a3SKim Phillips {
145422a550a3SKim Phillips 	int shift;
14554d1b1fd7SSuzuki K Poulose 	u64 access_type = etm4_get_comparator_access_type(config);
145622a550a3SKim Phillips 
145722a550a3SKim Phillips 	/* Configure the comparator */
145822a550a3SKim Phillips 	config->addr_val[comparator] = address;
145922a550a3SKim Phillips 	config->addr_acc[comparator] = access_type;
146022a550a3SKim Phillips 	config->addr_type[comparator] = type;
146122a550a3SKim Phillips 
146222a550a3SKim Phillips 	/*
146322a550a3SKim Phillips 	 * Configure ViewInst Start-Stop control register.
146422a550a3SKim Phillips 	 * Addresses configured to start tracing go from bit 0 to n-1,
146522a550a3SKim Phillips 	 * while those configured to stop tracing from 16 to 16 + n-1.
146622a550a3SKim Phillips 	 */
146722a550a3SKim Phillips 	shift = (type == ETM_ADDR_TYPE_START ? 0 : 16);
146822a550a3SKim Phillips 	config->vissctlr |= BIT(shift + comparator);
146922a550a3SKim Phillips }
147022a550a3SKim Phillips 
147122a550a3SKim Phillips static void etm4_set_default_filter(struct etmv4_config *config)
147222a550a3SKim Phillips {
147322a550a3SKim Phillips 	/* Trace everything 'default' filter achieved by no filtering */
147422a550a3SKim Phillips 	config->viiectlr = 0x0;
147522a550a3SKim Phillips 
147622a550a3SKim Phillips 	/*
147722a550a3SKim Phillips 	 * TRCVICTLR::SSSTATUS == 1, the start-stop logic is
147822a550a3SKim Phillips 	 * in the started state
147922a550a3SKim Phillips 	 */
14806ba7f2bcSJames Clark 	config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
148122a550a3SKim Phillips 	config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
148222a550a3SKim Phillips 
148322a550a3SKim Phillips 	/* No start-stop filtering for ViewInst */
148422a550a3SKim Phillips 	config->vissctlr = 0x0;
148522a550a3SKim Phillips }
148622a550a3SKim Phillips 
148722a550a3SKim Phillips static void etm4_set_default(struct etmv4_config *config)
148822a550a3SKim Phillips {
148922a550a3SKim Phillips 	if (WARN_ON_ONCE(!config))
149022a550a3SKim Phillips 		return;
149122a550a3SKim Phillips 
149222a550a3SKim Phillips 	/*
149322a550a3SKim Phillips 	 * Make default initialisation trace everything
149422a550a3SKim Phillips 	 *
149522a550a3SKim Phillips 	 * This is done by a minimum default config sufficient to enable
149622a550a3SKim Phillips 	 * full instruction trace - with a default filter for trace all
149722a550a3SKim Phillips 	 * achieved by having no filtering.
149822a550a3SKim Phillips 	 */
149922a550a3SKim Phillips 	etm4_set_default_config(config);
150022a550a3SKim Phillips 	etm4_set_default_filter(config);
150122a550a3SKim Phillips }
150222a550a3SKim Phillips 
150322a550a3SKim Phillips static int etm4_get_next_comparator(struct etmv4_drvdata *drvdata, u32 type)
150422a550a3SKim Phillips {
150522a550a3SKim Phillips 	int nr_comparator, index = 0;
150622a550a3SKim Phillips 	struct etmv4_config *config = &drvdata->config;
150722a550a3SKim Phillips 
150822a550a3SKim Phillips 	/*
150922a550a3SKim Phillips 	 * nr_addr_cmp holds the number of comparator _pair_, so time 2
151022a550a3SKim Phillips 	 * for the total number of comparators.
151122a550a3SKim Phillips 	 */
151222a550a3SKim Phillips 	nr_comparator = drvdata->nr_addr_cmp * 2;
151322a550a3SKim Phillips 
151422a550a3SKim Phillips 	/* Go through the tally of comparators looking for a free one. */
151522a550a3SKim Phillips 	while (index < nr_comparator) {
151622a550a3SKim Phillips 		switch (type) {
151722a550a3SKim Phillips 		case ETM_ADDR_TYPE_RANGE:
151822a550a3SKim Phillips 			if (config->addr_type[index] == ETM_ADDR_TYPE_NONE &&
151922a550a3SKim Phillips 			    config->addr_type[index + 1] == ETM_ADDR_TYPE_NONE)
152022a550a3SKim Phillips 				return index;
152122a550a3SKim Phillips 
152222a550a3SKim Phillips 			/* Address range comparators go in pairs */
152322a550a3SKim Phillips 			index += 2;
152422a550a3SKim Phillips 			break;
152522a550a3SKim Phillips 		case ETM_ADDR_TYPE_START:
152622a550a3SKim Phillips 		case ETM_ADDR_TYPE_STOP:
152722a550a3SKim Phillips 			if (config->addr_type[index] == ETM_ADDR_TYPE_NONE)
152822a550a3SKim Phillips 				return index;
152922a550a3SKim Phillips 
153022a550a3SKim Phillips 			/* Start/stop address can have odd indexes */
153122a550a3SKim Phillips 			index += 1;
153222a550a3SKim Phillips 			break;
153322a550a3SKim Phillips 		default:
153422a550a3SKim Phillips 			return -EINVAL;
153522a550a3SKim Phillips 		}
153622a550a3SKim Phillips 	}
153722a550a3SKim Phillips 
153822a550a3SKim Phillips 	/* If we are here all the comparators have been used. */
153922a550a3SKim Phillips 	return -ENOSPC;
154022a550a3SKim Phillips }
154122a550a3SKim Phillips 
154222a550a3SKim Phillips static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
154322a550a3SKim Phillips 				  struct perf_event *event)
154422a550a3SKim Phillips {
154522a550a3SKim Phillips 	int i, comparator, ret = 0;
154622a550a3SKim Phillips 	u64 address;
154722a550a3SKim Phillips 	struct etmv4_config *config = &drvdata->config;
154822a550a3SKim Phillips 	struct etm_filters *filters = event->hw.addr_filters;
154922a550a3SKim Phillips 
155022a550a3SKim Phillips 	if (!filters)
155122a550a3SKim Phillips 		goto default_filter;
155222a550a3SKim Phillips 
155322a550a3SKim Phillips 	/* Sync events with what Perf got */
155422a550a3SKim Phillips 	perf_event_addr_filters_sync(event);
155522a550a3SKim Phillips 
155622a550a3SKim Phillips 	/*
155722a550a3SKim Phillips 	 * If there are no filters to deal with simply go ahead with
155822a550a3SKim Phillips 	 * the default filter, i.e the entire address range.
155922a550a3SKim Phillips 	 */
156022a550a3SKim Phillips 	if (!filters->nr_filters)
156122a550a3SKim Phillips 		goto default_filter;
156222a550a3SKim Phillips 
156322a550a3SKim Phillips 	for (i = 0; i < filters->nr_filters; i++) {
156422a550a3SKim Phillips 		struct etm_filter *filter = &filters->etm_filter[i];
156522a550a3SKim Phillips 		enum etm_addr_type type = filter->type;
156622a550a3SKim Phillips 
156722a550a3SKim Phillips 		/* See if a comparator is free. */
156822a550a3SKim Phillips 		comparator = etm4_get_next_comparator(drvdata, type);
156922a550a3SKim Phillips 		if (comparator < 0) {
157022a550a3SKim Phillips 			ret = comparator;
157122a550a3SKim Phillips 			goto out;
157222a550a3SKim Phillips 		}
157322a550a3SKim Phillips 
157422a550a3SKim Phillips 		switch (type) {
157522a550a3SKim Phillips 		case ETM_ADDR_TYPE_RANGE:
157622a550a3SKim Phillips 			etm4_set_comparator_filter(config,
157722a550a3SKim Phillips 						   filter->start_addr,
157822a550a3SKim Phillips 						   filter->stop_addr,
157922a550a3SKim Phillips 						   comparator);
158022a550a3SKim Phillips 			/*
158122a550a3SKim Phillips 			 * TRCVICTLR::SSSTATUS == 1, the start-stop logic is
158222a550a3SKim Phillips 			 * in the started state
158322a550a3SKim Phillips 			 */
15846ba7f2bcSJames Clark 			config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
158522a550a3SKim Phillips 
158622a550a3SKim Phillips 			/* No start-stop filtering for ViewInst */
158722a550a3SKim Phillips 			config->vissctlr = 0x0;
158822a550a3SKim Phillips 			break;
158922a550a3SKim Phillips 		case ETM_ADDR_TYPE_START:
159022a550a3SKim Phillips 		case ETM_ADDR_TYPE_STOP:
159122a550a3SKim Phillips 			/* Get the right start or stop address */
159222a550a3SKim Phillips 			address = (type == ETM_ADDR_TYPE_START ?
159322a550a3SKim Phillips 				   filter->start_addr :
159422a550a3SKim Phillips 				   filter->stop_addr);
159522a550a3SKim Phillips 
159622a550a3SKim Phillips 			/* Configure comparator */
159722a550a3SKim Phillips 			etm4_set_start_stop_filter(config, address,
159822a550a3SKim Phillips 						   comparator, type);
159922a550a3SKim Phillips 
160022a550a3SKim Phillips 			/*
160122a550a3SKim Phillips 			 * If filters::ssstatus == 1, trace acquisition was
160222a550a3SKim Phillips 			 * started but the process was yanked away before the
1603c767c347SJilin Yuan 			 * stop address was hit.  As such the start/stop
160422a550a3SKim Phillips 			 * logic needs to be re-started so that tracing can
160522a550a3SKim Phillips 			 * resume where it left.
160622a550a3SKim Phillips 			 *
160722a550a3SKim Phillips 			 * The start/stop logic status when a process is
160822a550a3SKim Phillips 			 * scheduled out is checked in function
160922a550a3SKim Phillips 			 * etm4_disable_perf().
161022a550a3SKim Phillips 			 */
161122a550a3SKim Phillips 			if (filters->ssstatus)
16126ba7f2bcSJames Clark 				config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
161322a550a3SKim Phillips 
161422a550a3SKim Phillips 			/* No include/exclude filtering for ViewInst */
161522a550a3SKim Phillips 			config->viiectlr = 0x0;
161622a550a3SKim Phillips 			break;
161722a550a3SKim Phillips 		default:
161822a550a3SKim Phillips 			ret = -EINVAL;
161922a550a3SKim Phillips 			goto out;
162022a550a3SKim Phillips 		}
162122a550a3SKim Phillips 	}
162222a550a3SKim Phillips 
162322a550a3SKim Phillips 	goto out;
162422a550a3SKim Phillips 
162522a550a3SKim Phillips 
162622a550a3SKim Phillips default_filter:
162722a550a3SKim Phillips 	etm4_set_default_filter(config);
162822a550a3SKim Phillips 
162922a550a3SKim Phillips out:
163022a550a3SKim Phillips 	return ret;
163122a550a3SKim Phillips }
163222a550a3SKim Phillips 
163322a550a3SKim Phillips void etm4_config_trace_mode(struct etmv4_config *config)
163422a550a3SKim Phillips {
163522a550a3SKim Phillips 	u32 mode;
163622a550a3SKim Phillips 
163722a550a3SKim Phillips 	mode = config->mode;
163822a550a3SKim Phillips 	mode &= (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER);
163922a550a3SKim Phillips 
164022a550a3SKim Phillips 	/* excluding kernel AND user space doesn't make sense */
164122a550a3SKim Phillips 	WARN_ON_ONCE(mode == (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER));
164222a550a3SKim Phillips 
164322a550a3SKim Phillips 	/* nothing to do if neither flags are set */
164422a550a3SKim Phillips 	if (!(mode & ETM_MODE_EXCL_KERN) && !(mode & ETM_MODE_EXCL_USER))
164522a550a3SKim Phillips 		return;
164622a550a3SKim Phillips 
164722a550a3SKim Phillips 	etm4_set_victlr_access(config);
164822a550a3SKim Phillips }
164922a550a3SKim Phillips 
165022a550a3SKim Phillips static int etm4_online_cpu(unsigned int cpu)
165122a550a3SKim Phillips {
165222a550a3SKim Phillips 	if (!etmdrvdata[cpu])
16533c728e07STamas Zsoldos 		return etm4_probe_cpu(cpu);
165422a550a3SKim Phillips 
165522a550a3SKim Phillips 	if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable)
16561f5149c7SJames Clark 		coresight_enable_sysfs(etmdrvdata[cpu]->csdev);
165722a550a3SKim Phillips 	return 0;
165822a550a3SKim Phillips }
165922a550a3SKim Phillips 
166022a550a3SKim Phillips static int etm4_starting_cpu(unsigned int cpu)
166122a550a3SKim Phillips {
166222a550a3SKim Phillips 	if (!etmdrvdata[cpu])
166322a550a3SKim Phillips 		return 0;
166422a550a3SKim Phillips 
166522a550a3SKim Phillips 	spin_lock(&etmdrvdata[cpu]->spinlock);
166622a550a3SKim Phillips 	if (!etmdrvdata[cpu]->os_unlock)
166722a550a3SKim Phillips 		etm4_os_unlock(etmdrvdata[cpu]);
166822a550a3SKim Phillips 
1669c95c2733SJames Clark 	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
167022a550a3SKim Phillips 		etm4_enable_hw(etmdrvdata[cpu]);
167122a550a3SKim Phillips 	spin_unlock(&etmdrvdata[cpu]->spinlock);
167222a550a3SKim Phillips 	return 0;
167322a550a3SKim Phillips }
167422a550a3SKim Phillips 
167522a550a3SKim Phillips static int etm4_dying_cpu(unsigned int cpu)
167622a550a3SKim Phillips {
167722a550a3SKim Phillips 	if (!etmdrvdata[cpu])
167822a550a3SKim Phillips 		return 0;
167922a550a3SKim Phillips 
168022a550a3SKim Phillips 	spin_lock(&etmdrvdata[cpu]->spinlock);
1681c95c2733SJames Clark 	if (coresight_get_mode(etmdrvdata[cpu]->csdev))
168222a550a3SKim Phillips 		etm4_disable_hw(etmdrvdata[cpu]);
168322a550a3SKim Phillips 	spin_unlock(&etmdrvdata[cpu]->spinlock);
168422a550a3SKim Phillips 	return 0;
168522a550a3SKim Phillips }
168622a550a3SKim Phillips 
1687937d3f58SSuzuki K Poulose static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
168822a550a3SKim Phillips {
168922a550a3SKim Phillips 	int i, ret = 0;
169022a550a3SKim Phillips 	struct etmv4_save_state *state;
169102005282SSuzuki K Poulose 	struct coresight_device *csdev = drvdata->csdev;
169202005282SSuzuki K Poulose 	struct csdev_access *csa;
169302005282SSuzuki K Poulose 	struct device *etm_dev;
169402005282SSuzuki K Poulose 
169502005282SSuzuki K Poulose 	if (WARN_ON(!csdev))
169602005282SSuzuki K Poulose 		return -ENODEV;
169702005282SSuzuki K Poulose 
169802005282SSuzuki K Poulose 	etm_dev = &csdev->dev;
169902005282SSuzuki K Poulose 	csa = &csdev->access;
170022a550a3SKim Phillips 
170122a550a3SKim Phillips 	/*
170222a550a3SKim Phillips 	 * As recommended by 3.4.1 ("The procedure when powering down the PE")
170322a550a3SKim Phillips 	 * of ARM IHI 0064D
170422a550a3SKim Phillips 	 */
170522a550a3SKim Phillips 	dsb(sy);
170622a550a3SKim Phillips 	isb();
170722a550a3SKim Phillips 
170833d5573aSSuzuki K Poulose 	etm4_cs_unlock(drvdata, csa);
170922a550a3SKim Phillips 	/* Lock the OS lock to disable trace and external debugger access */
171022a550a3SKim Phillips 	etm4_os_lock(drvdata);
171122a550a3SKim Phillips 
171222a550a3SKim Phillips 	/* wait for TRCSTATR.PMSTABLE to go up */
171302005282SSuzuki K Poulose 	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) {
171422a550a3SKim Phillips 		dev_err(etm_dev,
171522a550a3SKim Phillips 			"timeout while waiting for PM Stable Status\n");
171622a550a3SKim Phillips 		etm4_os_unlock(drvdata);
171722a550a3SKim Phillips 		ret = -EBUSY;
171822a550a3SKim Phillips 		goto out;
171922a550a3SKim Phillips 	}
172022a550a3SKim Phillips 
172122a550a3SKim Phillips 	state = drvdata->save_state;
172222a550a3SKim Phillips 
1723f5bd5236SSuzuki K Poulose 	state->trcprgctlr = etm4x_read32(csa, TRCPRGCTLR);
17246288b4ceSSuzuki K Poulose 	if (drvdata->nr_pe)
1725f5bd5236SSuzuki K Poulose 		state->trcprocselr = etm4x_read32(csa, TRCPROCSELR);
1726f5bd5236SSuzuki K Poulose 	state->trcconfigr = etm4x_read32(csa, TRCCONFIGR);
1727f5bd5236SSuzuki K Poulose 	state->trcauxctlr = etm4x_read32(csa, TRCAUXCTLR);
1728f5bd5236SSuzuki K Poulose 	state->trceventctl0r = etm4x_read32(csa, TRCEVENTCTL0R);
1729f5bd5236SSuzuki K Poulose 	state->trceventctl1r = etm4x_read32(csa, TRCEVENTCTL1R);
1730f7289606SSuzuki K Poulose 	if (drvdata->stallctl)
1731f5bd5236SSuzuki K Poulose 		state->trcstallctlr = etm4x_read32(csa, TRCSTALLCTLR);
1732f5bd5236SSuzuki K Poulose 	state->trctsctlr = etm4x_read32(csa, TRCTSCTLR);
1733f5bd5236SSuzuki K Poulose 	state->trcsyncpr = etm4x_read32(csa, TRCSYNCPR);
1734f5bd5236SSuzuki K Poulose 	state->trcccctlr = etm4x_read32(csa, TRCCCCTLR);
1735f5bd5236SSuzuki K Poulose 	state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR);
1736f5bd5236SSuzuki K Poulose 	state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR);
173746bf8d7cSSuzuki K Poulose 	if (drvdata->q_filt)
1738f5bd5236SSuzuki K Poulose 		state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
173922a550a3SKim Phillips 
1740f5bd5236SSuzuki K Poulose 	state->trcvictlr = etm4x_read32(csa, TRCVICTLR);
1741f5bd5236SSuzuki K Poulose 	state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR);
1742f5bd5236SSuzuki K Poulose 	state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR);
174360c519c5SSuzuki K Poulose 	if (drvdata->nr_pe_cmp)
1744f5bd5236SSuzuki K Poulose 		state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR);
174522a550a3SKim Phillips 
174622a550a3SKim Phillips 	for (i = 0; i < drvdata->nrseqstate - 1; i++)
1747f5bd5236SSuzuki K Poulose 		state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));
174822a550a3SKim Phillips 
1749589d9282SJunhao He 	if (drvdata->nrseqstate) {
1750f5bd5236SSuzuki K Poulose 		state->trcseqrstevr = etm4x_read32(csa, TRCSEQRSTEVR);
1751f5bd5236SSuzuki K Poulose 		state->trcseqstr = etm4x_read32(csa, TRCSEQSTR);
1752589d9282SJunhao He 	}
1753f5bd5236SSuzuki K Poulose 	state->trcextinselr = etm4x_read32(csa, TRCEXTINSELR);
175422a550a3SKim Phillips 
175522a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_cntr; i++) {
1756f5bd5236SSuzuki K Poulose 		state->trccntrldvr[i] = etm4x_read32(csa, TRCCNTRLDVRn(i));
1757f5bd5236SSuzuki K Poulose 		state->trccntctlr[i] = etm4x_read32(csa, TRCCNTCTLRn(i));
1758f5bd5236SSuzuki K Poulose 		state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i));
175922a550a3SKim Phillips 	}
176022a550a3SKim Phillips 
1761*d6fc00d0SSuzuki K Poulose 	/* Resource selector pair 0 is reserved */
1762*d6fc00d0SSuzuki K Poulose 	for (i = 2; i < drvdata->nr_resource * 2; i++)
1763f5bd5236SSuzuki K Poulose 		state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i));
176422a550a3SKim Phillips 
176522a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
1766f5bd5236SSuzuki K Poulose 		state->trcssccr[i] = etm4x_read32(csa, TRCSSCCRn(i));
1767f5bd5236SSuzuki K Poulose 		state->trcsscsr[i] = etm4x_read32(csa, TRCSSCSRn(i));
1768f6a18f35SSuzuki K Poulose 		if (etm4x_sspcicrn_present(drvdata, i))
1769f5bd5236SSuzuki K Poulose 			state->trcsspcicr[i] = etm4x_read32(csa, TRCSSPCICRn(i));
177022a550a3SKim Phillips 	}
177122a550a3SKim Phillips 
177222a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
1773f5bd5236SSuzuki K Poulose 		state->trcacvr[i] = etm4x_read64(csa, TRCACVRn(i));
1774f5bd5236SSuzuki K Poulose 		state->trcacatr[i] = etm4x_read64(csa, TRCACATRn(i));
177522a550a3SKim Phillips 	}
177622a550a3SKim Phillips 
177722a550a3SKim Phillips 	/*
177822a550a3SKim Phillips 	 * Data trace stream is architecturally prohibited for A profile cores
177922a550a3SKim Phillips 	 * so we don't save (or later restore) trcdvcvr and trcdvcmr - As per
178022a550a3SKim Phillips 	 * section 1.3.4 ("Possible functional configurations of an ETMv4 trace
178122a550a3SKim Phillips 	 * unit") of ARM IHI 0064D.
178222a550a3SKim Phillips 	 */
178322a550a3SKim Phillips 
178422a550a3SKim Phillips 	for (i = 0; i < drvdata->numcidc; i++)
1785f5bd5236SSuzuki K Poulose 		state->trccidcvr[i] = etm4x_read64(csa, TRCCIDCVRn(i));
178622a550a3SKim Phillips 
178722a550a3SKim Phillips 	for (i = 0; i < drvdata->numvmidc; i++)
1788f5bd5236SSuzuki K Poulose 		state->trcvmidcvr[i] = etm4x_read64(csa, TRCVMIDCVRn(i));
178922a550a3SKim Phillips 
1790f5bd5236SSuzuki K Poulose 	state->trccidcctlr0 = etm4x_read32(csa, TRCCIDCCTLR0);
1791f2603b22SSuzuki K Poulose 	if (drvdata->numcidc > 4)
1792f5bd5236SSuzuki K Poulose 		state->trccidcctlr1 = etm4x_read32(csa, TRCCIDCCTLR1);
179322a550a3SKim Phillips 
1794f5bd5236SSuzuki K Poulose 	state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR0);
179593dd6440SSuzuki K Poulose 	if (drvdata->numvmidc > 4)
1796f5bd5236SSuzuki K Poulose 		state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR1);
179722a550a3SKim Phillips 
1798f5bd5236SSuzuki K Poulose 	state->trcclaimset = etm4x_read32(csa, TRCCLAIMCLR);
179922a550a3SKim Phillips 
1800df81b438SSuzuki K Poulose 	if (!drvdata->skip_power_up)
1801f5bd5236SSuzuki K Poulose 		state->trcpdcr = etm4x_read32(csa, TRCPDCR);
180222a550a3SKim Phillips 
180322a550a3SKim Phillips 	/* wait for TRCSTATR.IDLE to go up */
180402005282SSuzuki K Poulose 	if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
180522a550a3SKim Phillips 		dev_err(etm_dev,
180622a550a3SKim Phillips 			"timeout while waiting for Idle Trace Status\n");
180722a550a3SKim Phillips 		etm4_os_unlock(drvdata);
180822a550a3SKim Phillips 		ret = -EBUSY;
180922a550a3SKim Phillips 		goto out;
181022a550a3SKim Phillips 	}
181122a550a3SKim Phillips 
181222a550a3SKim Phillips 	drvdata->state_needs_restore = true;
181322a550a3SKim Phillips 
181422a550a3SKim Phillips 	/*
181522a550a3SKim Phillips 	 * Power can be removed from the trace unit now. We do this to
181622a550a3SKim Phillips 	 * potentially save power on systems that respect the TRCPDCR_PU
181722a550a3SKim Phillips 	 * despite requesting software to save/restore state.
181822a550a3SKim Phillips 	 */
1819df81b438SSuzuki K Poulose 	if (!drvdata->skip_power_up)
1820f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU),
1821f5bd5236SSuzuki K Poulose 				      TRCPDCR);
182222a550a3SKim Phillips out:
182333d5573aSSuzuki K Poulose 	etm4_cs_lock(drvdata, csa);
182422a550a3SKim Phillips 	return ret;
182522a550a3SKim Phillips }
182622a550a3SKim Phillips 
1827937d3f58SSuzuki K Poulose static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
1828937d3f58SSuzuki K Poulose {
1829937d3f58SSuzuki K Poulose 	int ret = 0;
1830937d3f58SSuzuki K Poulose 
1831937d3f58SSuzuki K Poulose 	/* Save the TRFCR irrespective of whether the ETM is ON */
18325f6fd1aaSSuzuki K Poulose 	if (drvdata->trfcr)
1833937d3f58SSuzuki K Poulose 		drvdata->save_trfcr = read_trfcr();
1834937d3f58SSuzuki K Poulose 	/*
1835937d3f58SSuzuki K Poulose 	 * Save and restore the ETM Trace registers only if
1836937d3f58SSuzuki K Poulose 	 * the ETM is active.
1837937d3f58SSuzuki K Poulose 	 */
1838c95c2733SJames Clark 	if (coresight_get_mode(drvdata->csdev) && drvdata->save_state)
1839937d3f58SSuzuki K Poulose 		ret = __etm4_cpu_save(drvdata);
1840937d3f58SSuzuki K Poulose 	return ret;
1841937d3f58SSuzuki K Poulose }
1842937d3f58SSuzuki K Poulose 
1843937d3f58SSuzuki K Poulose static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
184422a550a3SKim Phillips {
184522a550a3SKim Phillips 	int i;
184622a550a3SKim Phillips 	struct etmv4_save_state *state = drvdata->save_state;
18471e7ba33fSSuzuki K Poulose 	struct csdev_access *csa = &drvdata->csdev->access;
18481e7ba33fSSuzuki K Poulose 
18491e7ba33fSSuzuki K Poulose 	if (WARN_ON(!drvdata->csdev))
18501e7ba33fSSuzuki K Poulose 		return;
185122a550a3SKim Phillips 
185233d5573aSSuzuki K Poulose 	etm4_cs_unlock(drvdata, csa);
1853f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
185422a550a3SKim Phillips 
1855f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR);
18566288b4ceSSuzuki K Poulose 	if (drvdata->nr_pe)
1857f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR);
1858f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR);
1859f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcauxctlr, TRCAUXCTLR);
1860f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trceventctl0r, TRCEVENTCTL0R);
1861f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trceventctl1r, TRCEVENTCTL1R);
1862f7289606SSuzuki K Poulose 	if (drvdata->stallctl)
1863f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcstallctlr, TRCSTALLCTLR);
1864f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trctsctlr, TRCTSCTLR);
1865f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcsyncpr, TRCSYNCPR);
1866f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR);
1867f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR);
1868f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR);
186946bf8d7cSSuzuki K Poulose 	if (drvdata->q_filt)
1870f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
187122a550a3SKim Phillips 
1872f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR);
1873f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR);
1874f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR);
187560c519c5SSuzuki K Poulose 	if (drvdata->nr_pe_cmp)
1876f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR);
187722a550a3SKim Phillips 
187822a550a3SKim Phillips 	for (i = 0; i < drvdata->nrseqstate - 1; i++)
1879f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));
188022a550a3SKim Phillips 
1881589d9282SJunhao He 	if (drvdata->nrseqstate) {
1882f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcseqrstevr, TRCSEQRSTEVR);
1883f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcseqstr, TRCSEQSTR);
1884589d9282SJunhao He 	}
1885f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcextinselr, TRCEXTINSELR);
188622a550a3SKim Phillips 
188722a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_cntr; i++) {
1888f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trccntrldvr[i], TRCCNTRLDVRn(i));
1889f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trccntctlr[i], TRCCNTCTLRn(i));
1890f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i));
189122a550a3SKim Phillips 	}
189222a550a3SKim Phillips 
1893*d6fc00d0SSuzuki K Poulose 	/* Resource selector pair 0 is reserved */
1894*d6fc00d0SSuzuki K Poulose 	for (i = 2; i < drvdata->nr_resource * 2; i++)
1895f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i));
189622a550a3SKim Phillips 
189722a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
1898f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcssccr[i], TRCSSCCRn(i));
1899f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcsscsr[i], TRCSSCSRn(i));
1900f6a18f35SSuzuki K Poulose 		if (etm4x_sspcicrn_present(drvdata, i))
1901f5bd5236SSuzuki K Poulose 			etm4x_relaxed_write32(csa, state->trcsspcicr[i], TRCSSPCICRn(i));
190222a550a3SKim Phillips 	}
190322a550a3SKim Phillips 
190422a550a3SKim Phillips 	for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
1905f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, state->trcacvr[i], TRCACVRn(i));
1906f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, state->trcacatr[i], TRCACATRn(i));
190722a550a3SKim Phillips 	}
190822a550a3SKim Phillips 
190922a550a3SKim Phillips 	for (i = 0; i < drvdata->numcidc; i++)
1910f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, state->trccidcvr[i], TRCCIDCVRn(i));
191122a550a3SKim Phillips 
191222a550a3SKim Phillips 	for (i = 0; i < drvdata->numvmidc; i++)
1913f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write64(csa, state->trcvmidcvr[i], TRCVMIDCVRn(i));
191422a550a3SKim Phillips 
1915f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trccidcctlr0, TRCCIDCCTLR0);
1916f2603b22SSuzuki K Poulose 	if (drvdata->numcidc > 4)
1917f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trccidcctlr1, TRCCIDCCTLR1);
191822a550a3SKim Phillips 
1919f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR0);
192093dd6440SSuzuki K Poulose 	if (drvdata->numvmidc > 4)
1921f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR1);
192222a550a3SKim Phillips 
1923f5bd5236SSuzuki K Poulose 	etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
192422a550a3SKim Phillips 
1925df81b438SSuzuki K Poulose 	if (!drvdata->skip_power_up)
1926f5bd5236SSuzuki K Poulose 		etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR);
192722a550a3SKim Phillips 
192822a550a3SKim Phillips 	drvdata->state_needs_restore = false;
192922a550a3SKim Phillips 
193022a550a3SKim Phillips 	/*
193122a550a3SKim Phillips 	 * As recommended by section 4.3.7 ("Synchronization when using the
193222a550a3SKim Phillips 	 * memory-mapped interface") of ARM IHI 0064D
193322a550a3SKim Phillips 	 */
193422a550a3SKim Phillips 	dsb(sy);
193522a550a3SKim Phillips 	isb();
193622a550a3SKim Phillips 
193722a550a3SKim Phillips 	/* Unlock the OS lock to re-enable trace and external debug access */
193822a550a3SKim Phillips 	etm4_os_unlock(drvdata);
193933d5573aSSuzuki K Poulose 	etm4_cs_lock(drvdata, csa);
194022a550a3SKim Phillips }
194122a550a3SKim Phillips 
1942937d3f58SSuzuki K Poulose static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
1943937d3f58SSuzuki K Poulose {
19445f6fd1aaSSuzuki K Poulose 	if (drvdata->trfcr)
1945937d3f58SSuzuki K Poulose 		write_trfcr(drvdata->save_trfcr);
1946937d3f58SSuzuki K Poulose 	if (drvdata->state_needs_restore)
1947937d3f58SSuzuki K Poulose 		__etm4_cpu_restore(drvdata);
1948937d3f58SSuzuki K Poulose }
1949937d3f58SSuzuki K Poulose 
195022a550a3SKim Phillips static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
195122a550a3SKim Phillips 			      void *v)
195222a550a3SKim Phillips {
195322a550a3SKim Phillips 	struct etmv4_drvdata *drvdata;
195422a550a3SKim Phillips 	unsigned int cpu = smp_processor_id();
195522a550a3SKim Phillips 
195622a550a3SKim Phillips 	if (!etmdrvdata[cpu])
195722a550a3SKim Phillips 		return NOTIFY_OK;
195822a550a3SKim Phillips 
195922a550a3SKim Phillips 	drvdata = etmdrvdata[cpu];
196022a550a3SKim Phillips 
196122a550a3SKim Phillips 	if (WARN_ON_ONCE(drvdata->cpu != cpu))
196222a550a3SKim Phillips 		return NOTIFY_BAD;
196322a550a3SKim Phillips 
196422a550a3SKim Phillips 	switch (cmd) {
196522a550a3SKim Phillips 	case CPU_PM_ENTER:
196622a550a3SKim Phillips 		if (etm4_cpu_save(drvdata))
196722a550a3SKim Phillips 			return NOTIFY_BAD;
196822a550a3SKim Phillips 		break;
196922a550a3SKim Phillips 	case CPU_PM_EXIT:
197022a550a3SKim Phillips 	case CPU_PM_ENTER_FAILED:
197122a550a3SKim Phillips 		etm4_cpu_restore(drvdata);
197222a550a3SKim Phillips 		break;
197322a550a3SKim Phillips 	default:
197422a550a3SKim Phillips 		return NOTIFY_DONE;
197522a550a3SKim Phillips 	}
197622a550a3SKim Phillips 
197722a550a3SKim Phillips 	return NOTIFY_OK;
197822a550a3SKim Phillips }
197922a550a3SKim Phillips 
198022a550a3SKim Phillips static struct notifier_block etm4_cpu_pm_nb = {
198122a550a3SKim Phillips 	.notifier_call = etm4_cpu_pm_notify,
198222a550a3SKim Phillips };
198322a550a3SKim Phillips 
198422a550a3SKim Phillips /* Setup PM. Deals with error conditions and counts */
198522a550a3SKim Phillips static int __init etm4_pm_setup(void)
198622a550a3SKim Phillips {
198722a550a3SKim Phillips 	int ret;
198822a550a3SKim Phillips 
198922a550a3SKim Phillips 	ret = cpu_pm_register_notifier(&etm4_cpu_pm_nb);
199022a550a3SKim Phillips 	if (ret)
199122a550a3SKim Phillips 		return ret;
199222a550a3SKim Phillips 
199322a550a3SKim Phillips 	ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
199422a550a3SKim Phillips 					"arm/coresight4:starting",
199522a550a3SKim Phillips 					etm4_starting_cpu, etm4_dying_cpu);
199622a550a3SKim Phillips 
199722a550a3SKim Phillips 	if (ret)
199822a550a3SKim Phillips 		goto unregister_notifier;
199922a550a3SKim Phillips 
200022a550a3SKim Phillips 	ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
200122a550a3SKim Phillips 					"arm/coresight4:online",
200222a550a3SKim Phillips 					etm4_online_cpu, NULL);
200322a550a3SKim Phillips 
200422a550a3SKim Phillips 	/* HP dyn state ID returned in ret on success */
200522a550a3SKim Phillips 	if (ret > 0) {
200622a550a3SKim Phillips 		hp_online = ret;
200722a550a3SKim Phillips 		return 0;
200822a550a3SKim Phillips 	}
200922a550a3SKim Phillips 
201022a550a3SKim Phillips 	/* failed dyn state - remove others */
201122a550a3SKim Phillips 	cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
201222a550a3SKim Phillips 
201322a550a3SKim Phillips unregister_notifier:
201422a550a3SKim Phillips 	cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
201522a550a3SKim Phillips 	return ret;
201622a550a3SKim Phillips }
201722a550a3SKim Phillips 
201822a550a3SKim Phillips static void etm4_pm_clear(void)
201922a550a3SKim Phillips {
202022a550a3SKim Phillips 	cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
202122a550a3SKim Phillips 	cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
202222a550a3SKim Phillips 	if (hp_online) {
202322a550a3SKim Phillips 		cpuhp_remove_state_nocalls(hp_online);
202422a550a3SKim Phillips 		hp_online = 0;
202522a550a3SKim Phillips 	}
202622a550a3SKim Phillips }
202722a550a3SKim Phillips 
20283c728e07STamas Zsoldos static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
202922a550a3SKim Phillips {
203022a550a3SKim Phillips 	int ret;
203122a550a3SKim Phillips 	struct coresight_platform_data *pdata = NULL;
20323c728e07STamas Zsoldos 	struct device *dev = init_arg->dev;
20333c728e07STamas Zsoldos 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
203422a550a3SKim Phillips 	struct coresight_desc desc = { 0 };
203535e1c916SSuzuki K Poulose 	u8 major, minor;
203635e1c916SSuzuki K Poulose 	char *type_name;
203722a550a3SKim Phillips 
203822a550a3SKim Phillips 	if (!drvdata)
20393c728e07STamas Zsoldos 		return -EINVAL;
204022a550a3SKim Phillips 
20413c728e07STamas Zsoldos 	desc.access = *init_arg->csa;
204222a550a3SKim Phillips 
20438b94db1eSSuzuki K Poulose 	if (!drvdata->arch)
204422a550a3SKim Phillips 		return -EINVAL;
204522a550a3SKim Phillips 
204635e1c916SSuzuki K Poulose 	major = ETM_ARCH_MAJOR_VERSION(drvdata->arch);
204735e1c916SSuzuki K Poulose 	minor = ETM_ARCH_MINOR_VERSION(drvdata->arch);
204835e1c916SSuzuki K Poulose 
204935e1c916SSuzuki K Poulose 	if (etm4x_is_ete(drvdata)) {
205035e1c916SSuzuki K Poulose 		type_name = "ete";
205135e1c916SSuzuki K Poulose 		/* ETE v1 has major version == 0b101. Adjust this for logging.*/
205235e1c916SSuzuki K Poulose 		major -= 4;
205335e1c916SSuzuki K Poulose 	} else {
205435e1c916SSuzuki K Poulose 		type_name = "etm";
205535e1c916SSuzuki K Poulose 	}
205635e1c916SSuzuki K Poulose 
205735e1c916SSuzuki K Poulose 	desc.name = devm_kasprintf(dev, GFP_KERNEL,
205835e1c916SSuzuki K Poulose 				   "%s%d", type_name, drvdata->cpu);
205935e1c916SSuzuki K Poulose 	if (!desc.name)
206035e1c916SSuzuki K Poulose 		return -ENOMEM;
206135e1c916SSuzuki K Poulose 
206222a550a3SKim Phillips 	etm4_set_default(&drvdata->config);
206322a550a3SKim Phillips 
206422a550a3SKim Phillips 	pdata = coresight_get_platform_data(dev);
206522a550a3SKim Phillips 	if (IS_ERR(pdata))
206622a550a3SKim Phillips 		return PTR_ERR(pdata);
206722a550a3SKim Phillips 
2068c23bc382SSuzuki K Poulose 	dev->platform_data = pdata;
206922a550a3SKim Phillips 
207022a550a3SKim Phillips 	desc.type = CORESIGHT_DEV_TYPE_SOURCE;
207122a550a3SKim Phillips 	desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
207222a550a3SKim Phillips 	desc.ops = &etm4_cs_ops;
207322a550a3SKim Phillips 	desc.pdata = pdata;
207422a550a3SKim Phillips 	desc.dev = dev;
207522a550a3SKim Phillips 	desc.groups = coresight_etmv4_groups;
207622a550a3SKim Phillips 	drvdata->csdev = coresight_register(&desc);
207722a550a3SKim Phillips 	if (IS_ERR(drvdata->csdev))
207822a550a3SKim Phillips 		return PTR_ERR(drvdata->csdev);
207922a550a3SKim Phillips 
208022a550a3SKim Phillips 	ret = etm_perf_symlink(drvdata->csdev, true);
208122a550a3SKim Phillips 	if (ret) {
208222a550a3SKim Phillips 		coresight_unregister(drvdata->csdev);
208322a550a3SKim Phillips 		return ret;
208422a550a3SKim Phillips 	}
208522a550a3SKim Phillips 
2086810ac401SMike Leach 	/* register with config infrastructure & load any current features */
2087810ac401SMike Leach 	ret = etm4_cscfg_register(drvdata->csdev);
2088810ac401SMike Leach 	if (ret) {
2089810ac401SMike Leach 		coresight_unregister(drvdata->csdev);
2090810ac401SMike Leach 		return ret;
2091810ac401SMike Leach 	}
2092810ac401SMike Leach 
209322a550a3SKim Phillips 	etmdrvdata[drvdata->cpu] = drvdata;
209422a550a3SKim Phillips 
209535e1c916SSuzuki K Poulose 	dev_info(&drvdata->csdev->dev, "CPU%d: %s v%d.%d initialized\n",
209635e1c916SSuzuki K Poulose 		 drvdata->cpu, type_name, major, minor);
209722a550a3SKim Phillips 
209822a550a3SKim Phillips 	if (boot_enable) {
20991f5149c7SJames Clark 		coresight_enable_sysfs(drvdata->csdev);
210022a550a3SKim Phillips 		drvdata->boot_enable = true;
210122a550a3SKim Phillips 	}
210222a550a3SKim Phillips 
210322a550a3SKim Phillips 	return 0;
210422a550a3SKim Phillips }
210522a550a3SKim Phillips 
21065a1c7097SAnshuman Khandual static int etm4_probe(struct device *dev)
21073c728e07STamas Zsoldos {
21083095e90eSAnshuman Khandual 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
21093c728e07STamas Zsoldos 	struct csdev_access access = { 0 };
21103c728e07STamas Zsoldos 	struct etm4_init_arg init_arg = { 0 };
21113c728e07STamas Zsoldos 	struct etm4_init_arg *delayed;
21123c728e07STamas Zsoldos 
21133095e90eSAnshuman Khandual 	if (WARN_ON(!drvdata))
21143c728e07STamas Zsoldos 		return -ENOMEM;
21153c728e07STamas Zsoldos 
21163c728e07STamas Zsoldos 	if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE)
21173c728e07STamas Zsoldos 		pm_save_enable = coresight_loses_context_with_cpu(dev) ?
21183c728e07STamas Zsoldos 			       PARAM_PM_SAVE_SELF_HOSTED : PARAM_PM_SAVE_NEVER;
21193c728e07STamas Zsoldos 
21203c728e07STamas Zsoldos 	if (pm_save_enable != PARAM_PM_SAVE_NEVER) {
21213c728e07STamas Zsoldos 		drvdata->save_state = devm_kmalloc(dev,
21223c728e07STamas Zsoldos 				sizeof(struct etmv4_save_state), GFP_KERNEL);
21233c728e07STamas Zsoldos 		if (!drvdata->save_state)
21243c728e07STamas Zsoldos 			return -ENOMEM;
21253c728e07STamas Zsoldos 	}
21263c728e07STamas Zsoldos 
21273c728e07STamas Zsoldos 	spin_lock_init(&drvdata->spinlock);
21283c728e07STamas Zsoldos 
21293c728e07STamas Zsoldos 	drvdata->cpu = coresight_get_cpu(dev);
21303c728e07STamas Zsoldos 	if (drvdata->cpu < 0)
21313c728e07STamas Zsoldos 		return drvdata->cpu;
21323c728e07STamas Zsoldos 
21333c728e07STamas Zsoldos 	init_arg.dev = dev;
21343c728e07STamas Zsoldos 	init_arg.csa = &access;
21353c728e07STamas Zsoldos 
21363c728e07STamas Zsoldos 	/*
21373c728e07STamas Zsoldos 	 * Serialize against CPUHP callbacks to avoid race condition
21383c728e07STamas Zsoldos 	 * between the smp call and saving the delayed probe.
21393c728e07STamas Zsoldos 	 */
21403c728e07STamas Zsoldos 	cpus_read_lock();
21413c728e07STamas Zsoldos 	if (smp_call_function_single(drvdata->cpu,
21423c728e07STamas Zsoldos 				etm4_init_arch_data,  &init_arg, 1)) {
21433c728e07STamas Zsoldos 		/* The CPU was offline, try again once it comes online. */
21443c728e07STamas Zsoldos 		delayed = devm_kmalloc(dev, sizeof(*delayed), GFP_KERNEL);
21453c728e07STamas Zsoldos 		if (!delayed) {
21463c728e07STamas Zsoldos 			cpus_read_unlock();
21473c728e07STamas Zsoldos 			return -ENOMEM;
21483c728e07STamas Zsoldos 		}
21493c728e07STamas Zsoldos 
21503c728e07STamas Zsoldos 		*delayed = init_arg;
21513c728e07STamas Zsoldos 
21523c728e07STamas Zsoldos 		per_cpu(delayed_probe, drvdata->cpu) = delayed;
21533c728e07STamas Zsoldos 
21543c728e07STamas Zsoldos 		cpus_read_unlock();
21553c728e07STamas Zsoldos 		return 0;
21563c728e07STamas Zsoldos 	}
21573c728e07STamas Zsoldos 	cpus_read_unlock();
21583c728e07STamas Zsoldos 
21593c728e07STamas Zsoldos 	return etm4_add_coresight_dev(&init_arg);
21603c728e07STamas Zsoldos }
21613c728e07STamas Zsoldos 
2162c23bc382SSuzuki K Poulose static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
2163c23bc382SSuzuki K Poulose {
21643095e90eSAnshuman Khandual 	struct etmv4_drvdata *drvdata;
2165c23bc382SSuzuki K Poulose 	void __iomem *base;
2166c23bc382SSuzuki K Poulose 	struct device *dev = &adev->dev;
2167c23bc382SSuzuki K Poulose 	struct resource *res = &adev->res;
2168c23bc382SSuzuki K Poulose 	int ret;
2169c23bc382SSuzuki K Poulose 
2170c23bc382SSuzuki K Poulose 	/* Validity for the resource is already checked by the AMBA core */
2171c23bc382SSuzuki K Poulose 	base = devm_ioremap_resource(dev, res);
2172c23bc382SSuzuki K Poulose 	if (IS_ERR(base))
2173c23bc382SSuzuki K Poulose 		return PTR_ERR(base);
2174c23bc382SSuzuki K Poulose 
21753095e90eSAnshuman Khandual 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
21763095e90eSAnshuman Khandual 	if (!drvdata)
21773095e90eSAnshuman Khandual 		return -ENOMEM;
21783095e90eSAnshuman Khandual 
21794e3b9a6eSAnshuman Khandual 	drvdata->base = base;
21803095e90eSAnshuman Khandual 	dev_set_drvdata(dev, drvdata);
21815a1c7097SAnshuman Khandual 	ret = etm4_probe(dev);
2182c23bc382SSuzuki K Poulose 	if (!ret)
2183c23bc382SSuzuki K Poulose 		pm_runtime_put(&adev->dev);
2184c23bc382SSuzuki K Poulose 
2185c23bc382SSuzuki K Poulose 	return ret;
2186c23bc382SSuzuki K Poulose }
2187c23bc382SSuzuki K Poulose 
21885214b563SSuzuki K Poulose static int etm4_probe_platform_dev(struct platform_device *pdev)
21895214b563SSuzuki K Poulose {
219073d779a0SAnshuman Khandual 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
21913095e90eSAnshuman Khandual 	struct etmv4_drvdata *drvdata;
21925214b563SSuzuki K Poulose 	int ret;
21935214b563SSuzuki K Poulose 
21943095e90eSAnshuman Khandual 	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
21953095e90eSAnshuman Khandual 	if (!drvdata)
21963095e90eSAnshuman Khandual 		return -ENOMEM;
21973095e90eSAnshuman Khandual 
219873d779a0SAnshuman Khandual 	drvdata->pclk = coresight_get_enable_apb_pclk(&pdev->dev);
219973d779a0SAnshuman Khandual 	if (IS_ERR(drvdata->pclk))
220073d779a0SAnshuman Khandual 		return -ENODEV;
220173d779a0SAnshuman Khandual 
220273d779a0SAnshuman Khandual 	if (res) {
220373d779a0SAnshuman Khandual 		drvdata->base = devm_ioremap_resource(&pdev->dev, res);
220473d779a0SAnshuman Khandual 		if (IS_ERR(drvdata->base)) {
220573d779a0SAnshuman Khandual 			clk_put(drvdata->pclk);
220673d779a0SAnshuman Khandual 			return PTR_ERR(drvdata->base);
220773d779a0SAnshuman Khandual 		}
220873d779a0SAnshuman Khandual 	}
220973d779a0SAnshuman Khandual 
22103095e90eSAnshuman Khandual 	dev_set_drvdata(&pdev->dev, drvdata);
22115214b563SSuzuki K Poulose 	pm_runtime_get_noresume(&pdev->dev);
22125214b563SSuzuki K Poulose 	pm_runtime_set_active(&pdev->dev);
22135214b563SSuzuki K Poulose 	pm_runtime_enable(&pdev->dev);
22145214b563SSuzuki K Poulose 
22155a1c7097SAnshuman Khandual 	ret = etm4_probe(&pdev->dev);
22165214b563SSuzuki K Poulose 
22175214b563SSuzuki K Poulose 	pm_runtime_put(&pdev->dev);
2218caa41c47SAnshuman Khandual 	if (ret)
2219caa41c47SAnshuman Khandual 		pm_runtime_disable(&pdev->dev);
2220caa41c47SAnshuman Khandual 
22215214b563SSuzuki K Poulose 	return ret;
22225214b563SSuzuki K Poulose }
22235214b563SSuzuki K Poulose 
22243c728e07STamas Zsoldos static int etm4_probe_cpu(unsigned int cpu)
22253c728e07STamas Zsoldos {
22263c728e07STamas Zsoldos 	int ret;
22273c728e07STamas Zsoldos 	struct etm4_init_arg init_arg;
22283c728e07STamas Zsoldos 	struct csdev_access access = { 0 };
22293c728e07STamas Zsoldos 	struct etm4_init_arg *iap = *this_cpu_ptr(&delayed_probe);
22303c728e07STamas Zsoldos 
22313c728e07STamas Zsoldos 	if (!iap)
22323c728e07STamas Zsoldos 		return 0;
22333c728e07STamas Zsoldos 
22343c728e07STamas Zsoldos 	init_arg = *iap;
22353c728e07STamas Zsoldos 	devm_kfree(init_arg.dev, iap);
22363c728e07STamas Zsoldos 	*this_cpu_ptr(&delayed_probe) = NULL;
22373c728e07STamas Zsoldos 
22383c728e07STamas Zsoldos 	ret = pm_runtime_resume_and_get(init_arg.dev);
22393c728e07STamas Zsoldos 	if (ret < 0) {
22403c728e07STamas Zsoldos 		dev_err(init_arg.dev, "Failed to get PM runtime!\n");
22413c728e07STamas Zsoldos 		return 0;
22423c728e07STamas Zsoldos 	}
22433c728e07STamas Zsoldos 
22443c728e07STamas Zsoldos 	init_arg.csa = &access;
22453c728e07STamas Zsoldos 	etm4_init_arch_data(&init_arg);
22463c728e07STamas Zsoldos 
22473c728e07STamas Zsoldos 	etm4_add_coresight_dev(&init_arg);
22483c728e07STamas Zsoldos 
22493c728e07STamas Zsoldos 	pm_runtime_put(init_arg.dev);
22503c728e07STamas Zsoldos 	return 0;
22513c728e07STamas Zsoldos }
22523c728e07STamas Zsoldos 
225322a550a3SKim Phillips static struct amba_cs_uci_id uci_id_etm4[] = {
225422a550a3SKim Phillips 	{
225522a550a3SKim Phillips 		/*  ETMv4 UCI data */
2256d02dfac3SSuzuki K Poulose 		.devarch	= ETM_DEVARCH_ETMv4x_ARCH,
2257d02dfac3SSuzuki K Poulose 		.devarch_mask	= ETM_DEVARCH_ID_MASK,
225873d779a0SAnshuman Khandual 		.devtype	= CS_DEVTYPE_PE_TRACE,
225922a550a3SKim Phillips 	}
226022a550a3SKim Phillips };
226122a550a3SKim Phillips 
226245fe7befSArnd Bergmann static void clear_etmdrvdata(void *info)
226322a550a3SKim Phillips {
226422a550a3SKim Phillips 	int cpu = *(int *)info;
226522a550a3SKim Phillips 
226622a550a3SKim Phillips 	etmdrvdata[cpu] = NULL;
22673c728e07STamas Zsoldos 	per_cpu(delayed_probe, cpu) = NULL;
226822a550a3SKim Phillips }
226922a550a3SKim Phillips 
2270348ddab8SUwe Kleine-König static void etm4_remove_dev(struct etmv4_drvdata *drvdata)
227122a550a3SKim Phillips {
22723c728e07STamas Zsoldos 	bool had_delayed_probe;
227322a550a3SKim Phillips 	/*
2274c23bc382SSuzuki K Poulose 	 * Taking hotplug lock here to avoid racing between etm4_remove_dev()
2275c23bc382SSuzuki K Poulose 	 * and CPU hotplug call backs.
227622a550a3SKim Phillips 	 */
227722a550a3SKim Phillips 	cpus_read_lock();
22783c728e07STamas Zsoldos 
22793c728e07STamas Zsoldos 	had_delayed_probe = per_cpu(delayed_probe, drvdata->cpu);
22803c728e07STamas Zsoldos 
228122a550a3SKim Phillips 	/*
228222a550a3SKim Phillips 	 * The readers for etmdrvdata[] are CPU hotplug call backs
228322a550a3SKim Phillips 	 * and PM notification call backs. Change etmdrvdata[i] on
228422a550a3SKim Phillips 	 * CPU i ensures these call backs has consistent view
228522a550a3SKim Phillips 	 * inside one call back function.
228622a550a3SKim Phillips 	 */
228722a550a3SKim Phillips 	if (smp_call_function_single(drvdata->cpu, clear_etmdrvdata, &drvdata->cpu, 1))
22883c728e07STamas Zsoldos 		clear_etmdrvdata(&drvdata->cpu);
228922a550a3SKim Phillips 
229022a550a3SKim Phillips 	cpus_read_unlock();
229122a550a3SKim Phillips 
22923c728e07STamas Zsoldos 	if (!had_delayed_probe) {
22933c728e07STamas Zsoldos 		etm_perf_symlink(drvdata->csdev, false);
2294810ac401SMike Leach 		cscfg_unregister_csdev(drvdata->csdev);
229522a550a3SKim Phillips 		coresight_unregister(drvdata->csdev);
22963c728e07STamas Zsoldos 	}
229722a550a3SKim Phillips }
229822a550a3SKim Phillips 
2299348ddab8SUwe Kleine-König static void etm4_remove_amba(struct amba_device *adev)
2300c23bc382SSuzuki K Poulose {
2301c23bc382SSuzuki K Poulose 	struct etmv4_drvdata *drvdata = dev_get_drvdata(&adev->dev);
2302c23bc382SSuzuki K Poulose 
2303c23bc382SSuzuki K Poulose 	if (drvdata)
23041609faa9SUwe Kleine-König 		etm4_remove_dev(drvdata);
2305c23bc382SSuzuki K Poulose }
2306c23bc382SSuzuki K Poulose 
23074445e142SUwe Kleine-König static void etm4_remove_platform_dev(struct platform_device *pdev)
23085214b563SSuzuki K Poulose {
23095214b563SSuzuki K Poulose 	struct etmv4_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
23105214b563SSuzuki K Poulose 
23115214b563SSuzuki K Poulose 	if (drvdata)
2312c5f231f1SUwe Kleine-König 		etm4_remove_dev(drvdata);
23135214b563SSuzuki K Poulose 	pm_runtime_disable(&pdev->dev);
231473d779a0SAnshuman Khandual 
2315a4621fd1SAnshuman Khandual 	if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
231673d779a0SAnshuman Khandual 		clk_put(drvdata->pclk);
23175214b563SSuzuki K Poulose }
23185214b563SSuzuki K Poulose 
231922a550a3SKim Phillips static const struct amba_id etm4_ids[] = {
232022a550a3SKim Phillips 	CS_AMBA_ID(0x000bb95d),			/* Cortex-A53 */
232122a550a3SKim Phillips 	CS_AMBA_ID(0x000bb95e),			/* Cortex-A57 */
232222a550a3SKim Phillips 	CS_AMBA_ID(0x000bb95a),			/* Cortex-A72 */
232322a550a3SKim Phillips 	CS_AMBA_ID(0x000bb959),			/* Cortex-A73 */
232422a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000bb9da, uci_id_etm4),/* Cortex-A35 */
2325b8336ad9SChunyan Zhang 	CS_AMBA_UCI_ID(0x000bbd05, uci_id_etm4),/* Cortex-A55 */
2326b8336ad9SChunyan Zhang 	CS_AMBA_UCI_ID(0x000bbd0a, uci_id_etm4),/* Cortex-A75 */
232722a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000bbd0c, uci_id_etm4),/* Neoverse N1 */
2328ec585949SSai Prakash Ranjan 	CS_AMBA_UCI_ID(0x000bbd41, uci_id_etm4),/* Cortex-A78 */
232922a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000f0205, uci_id_etm4),/* Qualcomm Kryo */
233022a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000f0211, uci_id_etm4),/* Qualcomm Kryo */
233122a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000bb802, uci_id_etm4),/* Qualcomm Kryo 385 Cortex-A55 */
233222a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000bb803, uci_id_etm4),/* Qualcomm Kryo 385 Cortex-A75 */
233322a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000bb805, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A55 */
233422a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000bb804, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A76 */
23350605b89dSTao Zhang 	CS_AMBA_UCI_ID(0x000bbd0d, uci_id_etm4),/* Qualcomm Kryo 5XX Cortex-A77 */
233622a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000cc0af, uci_id_etm4),/* Marvell ThunderX2 */
233722a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000b6d01, uci_id_etm4),/* HiSilicon-Hip08 */
233822a550a3SKim Phillips 	CS_AMBA_UCI_ID(0x000b6d02, uci_id_etm4),/* HiSilicon-Hip09 */
2339ab5ca626SSuzuki K Poulose 	/*
2340ab5ca626SSuzuki K Poulose 	 * Match all PIDs with ETM4 DEVARCH. No need for adding any of the new
2341ab5ca626SSuzuki K Poulose 	 * CPUs to the list here.
2342ab5ca626SSuzuki K Poulose 	 */
2343ab5ca626SSuzuki K Poulose 	CS_AMBA_MATCH_ALL_UCI(uci_id_etm4),
234422a550a3SKim Phillips 	{},
234522a550a3SKim Phillips };
234622a550a3SKim Phillips 
234722a550a3SKim Phillips MODULE_DEVICE_TABLE(amba, etm4_ids);
234822a550a3SKim Phillips 
2349c23bc382SSuzuki K Poulose static struct amba_driver etm4x_amba_driver = {
235022a550a3SKim Phillips 	.drv = {
235122a550a3SKim Phillips 		.name   = "coresight-etm4x",
235222a550a3SKim Phillips 		.suppress_bind_attrs = true,
235322a550a3SKim Phillips 	},
2354c23bc382SSuzuki K Poulose 	.probe		= etm4_probe_amba,
2355c23bc382SSuzuki K Poulose 	.remove         = etm4_remove_amba,
235622a550a3SKim Phillips 	.id_table	= etm4_ids,
235722a550a3SKim Phillips };
235822a550a3SKim Phillips 
235973d779a0SAnshuman Khandual #ifdef CONFIG_PM
236073d779a0SAnshuman Khandual static int etm4_runtime_suspend(struct device *dev)
236173d779a0SAnshuman Khandual {
236273d779a0SAnshuman Khandual 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
236373d779a0SAnshuman Khandual 
236473d779a0SAnshuman Khandual 	if (drvdata->pclk && !IS_ERR(drvdata->pclk))
236573d779a0SAnshuman Khandual 		clk_disable_unprepare(drvdata->pclk);
236673d779a0SAnshuman Khandual 
236773d779a0SAnshuman Khandual 	return 0;
236873d779a0SAnshuman Khandual }
236973d779a0SAnshuman Khandual 
237073d779a0SAnshuman Khandual static int etm4_runtime_resume(struct device *dev)
237173d779a0SAnshuman Khandual {
237273d779a0SAnshuman Khandual 	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
237373d779a0SAnshuman Khandual 
237473d779a0SAnshuman Khandual 	if (drvdata->pclk && !IS_ERR(drvdata->pclk))
237573d779a0SAnshuman Khandual 		clk_prepare_enable(drvdata->pclk);
237673d779a0SAnshuman Khandual 
237773d779a0SAnshuman Khandual 	return 0;
237873d779a0SAnshuman Khandual }
237973d779a0SAnshuman Khandual #endif
238073d779a0SAnshuman Khandual 
238173d779a0SAnshuman Khandual static const struct dev_pm_ops etm4_dev_pm_ops = {
238273d779a0SAnshuman Khandual 	SET_RUNTIME_PM_OPS(etm4_runtime_suspend, etm4_runtime_resume, NULL)
238373d779a0SAnshuman Khandual };
238473d779a0SAnshuman Khandual 
23855214b563SSuzuki K Poulose static const struct of_device_id etm4_sysreg_match[] = {
23865214b563SSuzuki K Poulose 	{ .compatible	= "arm,coresight-etm4x-sysreg" },
238735e1c916SSuzuki K Poulose 	{ .compatible	= "arm,embedded-trace-extension" },
23885214b563SSuzuki K Poulose 	{}
23895214b563SSuzuki K Poulose };
23905214b563SSuzuki K Poulose 
2391134124acSSuzuki K Poulose #ifdef CONFIG_ACPI
2392134124acSSuzuki K Poulose static const struct acpi_device_id etm4x_acpi_ids[] = {
23938a519235SJames Clark 	{"ARMHC500", 0, 0, 0}, /* ARM CoreSight ETM4x */
2394134124acSSuzuki K Poulose 	{}
2395134124acSSuzuki K Poulose };
2396134124acSSuzuki K Poulose MODULE_DEVICE_TABLE(acpi, etm4x_acpi_ids);
2397134124acSSuzuki K Poulose #endif
2398134124acSSuzuki K Poulose 
23995214b563SSuzuki K Poulose static struct platform_driver etm4_platform_driver = {
24005214b563SSuzuki K Poulose 	.probe		= etm4_probe_platform_dev,
24014445e142SUwe Kleine-König 	.remove_new	= etm4_remove_platform_dev,
24025214b563SSuzuki K Poulose 	.driver			= {
24035214b563SSuzuki K Poulose 		.name			= "coresight-etm4x",
24045214b563SSuzuki K Poulose 		.of_match_table		= etm4_sysreg_match,
2405134124acSSuzuki K Poulose 		.acpi_match_table	= ACPI_PTR(etm4x_acpi_ids),
24065214b563SSuzuki K Poulose 		.suppress_bind_attrs	= true,
240773d779a0SAnshuman Khandual 		.pm			= &etm4_dev_pm_ops,
24085214b563SSuzuki K Poulose 	},
24095214b563SSuzuki K Poulose };
24105214b563SSuzuki K Poulose 
241122a550a3SKim Phillips static int __init etm4x_init(void)
241222a550a3SKim Phillips {
241322a550a3SKim Phillips 	int ret;
241422a550a3SKim Phillips 
241522a550a3SKim Phillips 	ret = etm4_pm_setup();
241622a550a3SKim Phillips 
241722a550a3SKim Phillips 	/* etm4_pm_setup() does its own cleanup - exit on error */
241822a550a3SKim Phillips 	if (ret)
241922a550a3SKim Phillips 		return ret;
242022a550a3SKim Phillips 
2421c23bc382SSuzuki K Poulose 	ret = amba_driver_register(&etm4x_amba_driver);
242222a550a3SKim Phillips 	if (ret) {
24235214b563SSuzuki K Poulose 		pr_err("Error registering etm4x AMBA driver\n");
24245214b563SSuzuki K Poulose 		goto clear_pm;
242522a550a3SKim Phillips 	}
242622a550a3SKim Phillips 
24275214b563SSuzuki K Poulose 	ret = platform_driver_register(&etm4_platform_driver);
24285214b563SSuzuki K Poulose 	if (!ret)
24295214b563SSuzuki K Poulose 		return 0;
24305214b563SSuzuki K Poulose 
24315214b563SSuzuki K Poulose 	pr_err("Error registering etm4x platform driver\n");
24325214b563SSuzuki K Poulose 	amba_driver_unregister(&etm4x_amba_driver);
24335214b563SSuzuki K Poulose 
24345214b563SSuzuki K Poulose clear_pm:
24355214b563SSuzuki K Poulose 	etm4_pm_clear();
243622a550a3SKim Phillips 	return ret;
243722a550a3SKim Phillips }
243822a550a3SKim Phillips 
243922a550a3SKim Phillips static void __exit etm4x_exit(void)
244022a550a3SKim Phillips {
2441c23bc382SSuzuki K Poulose 	amba_driver_unregister(&etm4x_amba_driver);
24425214b563SSuzuki K Poulose 	platform_driver_unregister(&etm4_platform_driver);
244322a550a3SKim Phillips 	etm4_pm_clear();
244422a550a3SKim Phillips }
244522a550a3SKim Phillips 
244622a550a3SKim Phillips module_init(etm4x_init);
244722a550a3SKim Phillips module_exit(etm4x_exit);
244822a550a3SKim Phillips 
244922a550a3SKim Phillips MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");
245022a550a3SKim Phillips MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");
245122a550a3SKim Phillips MODULE_DESCRIPTION("Arm CoreSight Program Flow Trace v4.x driver");
245222a550a3SKim Phillips MODULE_LICENSE("GPL v2");
2453