diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 2637096c4621..4cc207d42976 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -58,7 +58,8 @@ MODULE_PARM_DESC(pm_save_enable,
 static struct etmv4_drvdata *etmdrvdata[NR_CPUS];
 static void etm4_set_default_config(struct etmv4_config *config);
 static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
-				  struct perf_event *event);
+				  struct perf_event *event,
+				  struct coresight_device *csdev);
 static u64 etm4_get_access_type(struct etmv4_config *config);
 
 static enum cpuhp_state hp_online;
@@ -478,91 +479,6 @@ static void etm4_enable_hw_smp_call(void *info)
 	arg->rc = etm4_enable_hw(arg->drvdata);
 }
 
-/*
- * The goal of function etm4_config_timestamp_event() is to configure a
- * counter that will tell the tracer to emit a timestamp packet when it
- * reaches zero.  This is done in order to get a more fine grained idea
- * of when instructions are executed so that they can be correlated
- * with execution on other CPUs.
- *
- * To do this the counter itself is configured to self reload and
- * TRCRSCTLR1 (always true) used to get the counter to decrement.  From
- * there a resource selector is configured with the counter and the
- * timestamp control register to use the resource selector to trigger the
- * event that will insert a timestamp packet in the stream.
- */
-static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
-{
-	int ctridx, ret = -EINVAL;
-	int counter, rselector;
-	u32 val = 0;
-	struct etmv4_config *config = &drvdata->config;
-
-	/* No point in trying if we don't have at least one counter */
-	if (!drvdata->nr_cntr)
-		goto out;
-
-	/* Find a counter that hasn't been initialised */
-	for (ctridx = 0; ctridx < drvdata->nr_cntr; ctridx++)
-		if (config->cntr_val[ctridx] == 0)
-			break;
-
-	/* All the counters have been configured already, bail out */
-	if (ctridx == drvdata->nr_cntr) {
-		pr_debug("%s: no available counter found\n", __func__);
-		ret = -ENOSPC;
-		goto out;
-	}
-
-	/*
-	 * Searching for an available resource selector to use, starting at
-	 * '2' since every implementation has at least 2 resource selector.
-	 * ETMIDR4 gives the number of resource selector _pairs_,
-	 * hence multiply by 2.
-	 */
-	for (rselector = 2; rselector < drvdata->nr_resource * 2; rselector++)
-		if (!config->res_ctrl[rselector])
-			break;
-
-	if (rselector == drvdata->nr_resource * 2) {
-		pr_debug("%s: no available resource selector found\n",
-			 __func__);
-		ret = -ENOSPC;
-		goto out;
-	}
-
-	/* Remember what counter we used */
-	counter = 1 << ctridx;
-
-	/*
-	 * Initialise original and reload counter value to the smallest
-	 * possible value in order to get as much precision as we can.
-	 */
-	config->cntr_val[ctridx] = 1;
-	config->cntrldvr[ctridx] = 1;
-
-	/* Set the trace counter control register */
-	val =  0x1 << 16	|  /* Bit 16, reload counter automatically */
-	       0x0 << 7		|  /* Select single resource selector */
-	       0x1;		   /* Resource selector 1, i.e always true */
-
-	config->cntr_ctrl[ctridx] = val;
-
-	val = 0x2 << 16		| /* Group 0b0010 - Counter and sequencers */
-	      counter << 0;	  /* Counter to use */
-
-	config->res_ctrl[rselector] = val;
-
-	val = 0x0 << 7		| /* Select single resource selector */
-	      rselector;	  /* Resource selector */
-
-	config->ts_ctrl = val;
-
-	ret = 0;
-out:
-	return ret;
-}
-
 static int etm4_parse_event_config(struct coresight_device *csdev,
 				   struct perf_event *event)
 {
@@ -570,6 +486,7 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
 	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	struct etmv4_config *config = &drvdata->config;
 	struct perf_event_attr *attr = &event->attr;
+	struct etm4_cfg_resources *res_inuse;
 	unsigned long cfg_hash;
 	int preset;
 
@@ -581,6 +498,10 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
 	/* Clear configuration from previous run */
 	memset(config, 0, sizeof(struct etmv4_config));
 
+	/* clear any resources still marked as inuse */
+	res_inuse = &((struct cscfg_res_impl_used *)csdev->cscfg_res_mask)->used;
+	memset(res_inuse, 0, sizeof(struct etm4_cfg_resources));
+
 	if (attr->exclude_kernel)
 		config->mode = ETM_MODE_EXCL_KERN;
 
@@ -590,37 +511,51 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
 	/* Always start from the default config */
 	etm4_set_default_config(config);
 
+	/*
+	 * First set any selected configuration and preset.
+	 *
+	 * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
+	 * in the perf attributes defined in coresight-etm-perf.c.
+	 * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
+	 * A zero configid means no configuration active, preset = 0 means no preset selected.
+	 */
+	if (attr->config2 & GENMASK_ULL(63, 32)) {
+		cfg_hash = (u32)(attr->config2 >> 32);
+		preset = attr->config & 0xF;
+		ret =  cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
+		if (ret)
+			goto out;
+	}
+
+	/*
+	 * once any config is set, then we can add any perf options -
+	 * using resource management to prevent clashes & not set items that
+	 * are currently set.
+	 */
+
 	/* Configure filters specified on the perf cmd line, if any. */
-	ret = etm4_set_event_filters(drvdata, event);
+	ret = etm4_set_event_filters(drvdata, event, csdev);
 	if (ret)
-		goto out;
+		goto out_disable_cfg;
 
 	/* Go from generic option to ETMv4 specifics */
-	if (attr->config & BIT(ETM_OPT_CYCACC)) {
+	if ((attr->config & BIT(ETM_OPT_CYCACC)) && !res_inuse->cycle_cnt) {
 		config->cfg |= BIT(4);
 		/* TRM: Must program this for cycacc to work */
 		config->ccctlr = ETM_CYC_THRESHOLD_DEFAULT;
 	}
-	if (attr->config & BIT(ETM_OPT_TS)) {
+	if ((attr->config & BIT(ETM_OPT_TS)) && !res_inuse->ts_rate) {
 		/*
 		 * Configure timestamps to be emitted at regular intervals in
 		 * order to correlate instructions executed on different CPUs
-		 * (CPU-wide trace scenarios).
+		 * (CPU-wide trace scenarios). We use the built in ts rate function
+		 * to manage any resource conflicts. Request a rate of 1 to maximise
+		 * freqency of timestamps.
 		 */
-		ret = etm4_config_timestamp_event(drvdata);
-
-		/*
-		 * No need to go further if timestamp intervals can't
-		 * be configured.
-		 */
-		if (ret)
-			goto out;
-
-		/* bit[11], Global timestamp tracing bit */
-		config->cfg |= BIT(11);
+		etm4_cfg_set_ts_rate(csdev, 1);
 	}
 
-	if (attr->config & BIT(ETM_OPT_CTXTID))
+	if ((attr->config & BIT(ETM_OPT_CTXTID)) && !res_inuse->ctxt_id)
 		/* bit[6], Context ID tracing bit */
 		config->cfg |= BIT(ETM4_CFG_BIT_CTXTID);
 
@@ -632,30 +567,20 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
 	if (attr->config & BIT(ETM_OPT_CTXTID2)) {
 		if (!is_kernel_in_hyp_mode()) {
 			ret = -EINVAL;
-			goto out;
+			goto out_disable_cfg;
 		}
 		config->cfg |= BIT(ETM4_CFG_BIT_VMID) | BIT(ETM4_CFG_BIT_VMID_OPT);
 	}
 
 	/* return stack - enable if selected and supported */
-	if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack)
+	if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack && !res_inuse->return_stack)
 		/* bit[12], Return stack enable bit */
 		config->cfg |= BIT(12);
 
-	/*
-	 * Set any selected configuration and preset.
-	 *
-	 * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
-	 * in the perf attributes defined in coresight-etm-perf.c.
-	 * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
-	 * A zero configid means no configuration active, preset = 0 means no preset selected.
-	 */
-	if (attr->config2 & GENMASK_ULL(63, 32)) {
-		cfg_hash = (u32)(attr->config2 >> 32);
-		preset = attr->config & 0xF;
-		ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
-	}
+	return 0;
 
+out_disable_cfg:
+	cscfg_csdev_disable_active_config(csdev);
 out:
 	return ret;
 }
@@ -871,6 +796,8 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
 	spin_unlock(&drvdata->spinlock);
 	cpus_read_unlock();
 
+	cscfg_csdev_disable_active_config(csdev);
+
 	dev_dbg(&csdev->dev, "ETM tracing disabled\n");
 }
 
@@ -1375,52 +1302,37 @@ static void etm4_set_default(struct etmv4_config *config)
 	etm4_set_default_filter(config);
 }
 
-static int etm4_get_next_comparator(struct etmv4_drvdata *drvdata, u32 type)
+static int etm4_get_next_comparator_res(struct cscfg_res_impl_used *res,
+					u32 type)
 {
-	int nr_comparator, index = 0;
-	struct etmv4_config *config = &drvdata->config;
-
-	/*
-	 * nr_addr_cmp holds the number of comparator _pair_, so time 2
-	 * for the total number of comparators.
-	 */
-	nr_comparator = drvdata->nr_addr_cmp * 2;
+	switch (type) {
+	case ETM_ADDR_TYPE_RANGE:
+		return etm4_res_find_addr_comp_pair(res);
 
-	/* Go through the tally of comparators looking for a free one. */
-	while (index < nr_comparator) {
-		switch (type) {
-		case ETM_ADDR_TYPE_RANGE:
-			if (config->addr_type[index] == ETM_ADDR_TYPE_NONE &&
-			    config->addr_type[index + 1] == ETM_ADDR_TYPE_NONE)
-				return index;
-
-			/* Address range comparators go in pairs */
-			index += 2;
-			break;
-		case ETM_ADDR_TYPE_START:
-		case ETM_ADDR_TYPE_STOP:
-			if (config->addr_type[index] == ETM_ADDR_TYPE_NONE)
-				return index;
-
-			/* Start/stop address can have odd indexes */
-			index += 1;
-			break;
-		default:
-			return -EINVAL;
-		}
+	case ETM_ADDR_TYPE_START:
+	case ETM_ADDR_TYPE_STOP:
+		return etm4_res_find_addr_comparator(res);
 	}
-
-	/* If we are here all the comparators have been used. */
-	return -ENOSPC;
+	return -EINVAL;
 }
 
+/*
+ * Called to set up perf event filters - after any selected configuration.
+ * This allows the perf command line filters to be used in combination with
+ * any selected configuration.
+ *
+ * Use the config resources to find available comparators - only set default
+ * filter if no previous configuration has set up filtering.
+ */
 static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
-				  struct perf_event *event)
+				  struct perf_event *event,
+				  struct coresight_device *csdev)
 {
 	int i, comparator, ret = 0;
 	u64 address;
 	struct etmv4_config *config = &drvdata->config;
 	struct etm_filters *filters = event->hw.addr_filters;
+	struct cscfg_res_impl_used *res = (struct cscfg_res_impl_used *)csdev->cscfg_res_mask;
 
 	if (!filters)
 		goto default_filter;
@@ -1440,7 +1352,7 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
 		enum etm_addr_type type = filter->type;
 
 		/* See if a comparator is free. */
-		comparator = etm4_get_next_comparator(drvdata, type);
+		comparator = etm4_get_next_comparator_res(res, type);
 		if (comparator < 0) {
 			ret = comparator;
 			goto out;
@@ -1457,10 +1369,8 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
 			 * in the started state
 			 */
 			config->vinst_ctrl |= BIT(9);
-
-			/* No start-stop filtering for ViewInst */
-			config->vissctlr = 0x0;
 			break;
+
 		case ETM_ADDR_TYPE_START:
 		case ETM_ADDR_TYPE_STOP:
 			/* Get the right start or stop address */
@@ -1485,10 +1395,8 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
 			 */
 			if (filters->ssstatus)
 				config->vinst_ctrl |= BIT(9);
-
-			/* No include/exclude filtering for ViewInst */
-			config->viiectlr = 0x0;
 			break;
+
 		default:
 			ret = -EINVAL;
 			goto out;
@@ -1497,9 +1405,10 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
 
 	goto out;
 
-
 default_filter:
-	etm4_set_default_filter(config);
+	/* if no filtering has been set by any other method - set default here */
+	if (!config->viiectlr && !config->vissctlr)
+		etm4_set_default_filter(config);
 
 out:
 	return ret;
@@ -2161,10 +2070,19 @@ static int __init etm4x_init(void)
 	}
 
 	ret = platform_driver_register(&etm4_platform_driver);
+	if (ret) {
+		pr_err("Error registering etm4x platform driver\n");
+		goto clear_amba;
+	}
+
+	ret = etm4_cscfg_load_builtin_cfg();
 	if (!ret)
 		return 0;
 
-	pr_err("Error registering etm4x platform driver\n");
+	pr_err("Error loading etm4x coresight configurations\n");
+	platform_driver_unregister(&etm4_platform_driver);
+
+clear_amba:
 	amba_driver_unregister(&etm4x_amba_driver);
 
 clear_pm:
@@ -2174,6 +2092,7 @@ static int __init etm4x_init(void)
 
 static void __exit etm4x_exit(void)
 {
+	etm4_cscfg_unload_builtin_cfg();
 	amba_driver_unregister(&etm4x_amba_driver);
 	platform_driver_unregister(&etm4_platform_driver);
 	etm4_pm_clear();
