brintos

brintos / linux-shallow public Read only

0
0
Text · 25.2 KiB · d2b5a57 Raw
1015 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 Linaro Limited, All rights reserved.4 * Author: Mike Leach <mike.leach@linaro.org>5 */6 7#include <linux/amba/bus.h>8#include <linux/atomic.h>9#include <linux/bits.h>10#include <linux/coresight.h>11#include <linux/cpu_pm.h>12#include <linux/cpuhotplug.h>13#include <linux/device.h>14#include <linux/io.h>15#include <linux/kernel.h>16#include <linux/list.h>17#include <linux/mutex.h>18#include <linux/pm_runtime.h>19#include <linux/property.h>20#include <linux/spinlock.h>21 22#include "coresight-priv.h"23#include "coresight-cti.h"24 25/*26 * CTI devices can be associated with a PE, or be connected to CoreSight27 * hardware. We have a list of all CTIs irrespective of CPU bound or28 * otherwise.29 *30 * We assume that the non-CPU CTIs are always powered as we do with sinks etc.31 *32 * We leave the client to figure out if all the CTIs are interconnected with33 * the same CTM, in general this is the case but does not always have to be.34 */35 36/* net of CTI devices connected via CTM */37static LIST_HEAD(ect_net);38 39/* protect the list */40static DEFINE_MUTEX(ect_mutex);41 42#define csdev_to_cti_drvdata(csdev)	\43	dev_get_drvdata(csdev->dev.parent)44 45/* power management handling */46static int nr_cti_cpu;47 48/* quick lookup list for CPU bound CTIs when power handling */49static struct cti_drvdata *cti_cpu_drvdata[NR_CPUS];50 51/*52 * CTI naming. CTI bound to cores will have the name cti_cpu<N> where53 * N is the CPU ID. System CTIs will have the name cti_sys<I> where I54 * is an index allocated by order of discovery.55 *56 * CTI device name list - for CTI not bound to cores.57 */58DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys");59 60/* write set of regs to hardware - call with spinlock claimed */61void cti_write_all_hw_regs(struct cti_drvdata *drvdata)62{63	struct cti_config *config = &drvdata->config;64	int i;65 66	CS_UNLOCK(drvdata->base);67 68	/* disable CTI before writing registers */69	writel_relaxed(0, drvdata->base + CTICONTROL);70 71	/* write the CTI trigger registers */72	for (i = 0; i < config->nr_trig_max; i++) {73		writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i));74		writel_relaxed(config->ctiouten[i],75			       drvdata->base + CTIOUTEN(i));76	}77 78	/* other regs */79	writel_relaxed(config->ctigate, drvdata->base + CTIGATE);80	writel_relaxed(config->asicctl, drvdata->base + ASICCTL);81	writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);82 83	/* re-enable CTI */84	writel_relaxed(1, drvdata->base + CTICONTROL);85 86	CS_LOCK(drvdata->base);87}88 89/* write regs to hardware and enable */90static int cti_enable_hw(struct cti_drvdata *drvdata)91{92	struct cti_config *config = &drvdata->config;93	unsigned long flags;94	int rc = 0;95 96	spin_lock_irqsave(&drvdata->spinlock, flags);97 98	/* no need to do anything if enabled or unpowered*/99	if (config->hw_enabled || !config->hw_powered)100		goto cti_state_unchanged;101 102	/* claim the device */103	rc = coresight_claim_device(drvdata->csdev);104	if (rc)105		goto cti_err_not_enabled;106 107	cti_write_all_hw_regs(drvdata);108 109	config->hw_enabled = true;110	drvdata->config.enable_req_count++;111	spin_unlock_irqrestore(&drvdata->spinlock, flags);112	return rc;113 114cti_state_unchanged:115	drvdata->config.enable_req_count++;116 117	/* cannot enable due to error */118cti_err_not_enabled:119	spin_unlock_irqrestore(&drvdata->spinlock, flags);120	return rc;121}122 123/* re-enable CTI on CPU when using CPU hotplug */124static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)125{126	struct cti_config *config = &drvdata->config;127 128	spin_lock(&drvdata->spinlock);129	config->hw_powered = true;130 131	/* no need to do anything if no enable request */132	if (!drvdata->config.enable_req_count)133		goto cti_hp_not_enabled;134 135	/* try to claim the device */136	if (coresight_claim_device(drvdata->csdev))137		goto cti_hp_not_enabled;138 139	cti_write_all_hw_regs(drvdata);140	config->hw_enabled = true;141	spin_unlock(&drvdata->spinlock);142	return;143 144	/* did not re-enable due to no claim / no request */145cti_hp_not_enabled:146	spin_unlock(&drvdata->spinlock);147}148 149/* disable hardware */150static int cti_disable_hw(struct cti_drvdata *drvdata)151{152	struct cti_config *config = &drvdata->config;153	struct coresight_device *csdev = drvdata->csdev;154	int ret = 0;155 156	spin_lock(&drvdata->spinlock);157 158	/* don't allow negative refcounts, return an error */159	if (!drvdata->config.enable_req_count) {160		ret = -EINVAL;161		goto cti_not_disabled;162	}163 164	/* check refcount - disable on 0 */165	if (--drvdata->config.enable_req_count > 0)166		goto cti_not_disabled;167 168	/* no need to do anything if disabled or cpu unpowered */169	if (!config->hw_enabled || !config->hw_powered)170		goto cti_not_disabled;171 172	CS_UNLOCK(drvdata->base);173 174	/* disable CTI */175	writel_relaxed(0, drvdata->base + CTICONTROL);176	config->hw_enabled = false;177 178	coresight_disclaim_device_unlocked(csdev);179	CS_LOCK(drvdata->base);180	spin_unlock(&drvdata->spinlock);181	return ret;182 183	/* not disabled this call */184cti_not_disabled:185	spin_unlock(&drvdata->spinlock);186	return ret;187}188 189void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value)190{191	CS_UNLOCK(drvdata->base);192	writel_relaxed(value, drvdata->base + offset);193	CS_LOCK(drvdata->base);194}195 196void cti_write_intack(struct device *dev, u32 ackval)197{198	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);199	struct cti_config *config = &drvdata->config;200 201	spin_lock(&drvdata->spinlock);202	/* write if enabled */203	if (cti_active(config))204		cti_write_single_reg(drvdata, CTIINTACK, ackval);205	spin_unlock(&drvdata->spinlock);206}207 208/*209 * Look at the HW DEVID register for some of the HW settings.210 * DEVID[15:8] - max number of in / out triggers.211 */212#define CTI_DEVID_MAXTRIGS(devid_val) ((int) BMVAL(devid_val, 8, 15))213 214/* DEVID[19:16] - number of CTM channels */215#define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19))216 217static void cti_set_default_config(struct device *dev,218				   struct cti_drvdata *drvdata)219{220	struct cti_config *config = &drvdata->config;221	u32 devid;222 223	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);224	config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid);225 226	/*227	 * no current hardware should exceed this, but protect the driver228	 * in case of fault / out of spec hw229	 */230	if (config->nr_trig_max > CTIINOUTEN_MAX) {231		dev_warn_once(dev,232			"Limiting HW MaxTrig value(%d) to driver max(%d)\n",233			config->nr_trig_max, CTIINOUTEN_MAX);234		config->nr_trig_max = CTIINOUTEN_MAX;235	}236 237	config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);238 239	/* Most regs default to 0 as zalloc'ed except...*/240	config->trig_filter_enable = true;241	config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);242	config->enable_req_count = 0;243}244 245/*246 * Add a connection entry to the list of connections for this247 * CTI device.248 */249int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,250			     struct cti_trig_con *tc,251			     struct coresight_device *csdev,252			     const char *assoc_dev_name)253{254	struct cti_device *cti_dev = &drvdata->ctidev;255 256	tc->con_dev = csdev;257	/*258	 * Prefer actual associated CS device dev name to supplied value -259	 * which is likely to be node name / other conn name.260	 */261	if (csdev)262		tc->con_dev_name = dev_name(&csdev->dev);263	else if (assoc_dev_name != NULL) {264		tc->con_dev_name = devm_kstrdup(dev,265						assoc_dev_name, GFP_KERNEL);266		if (!tc->con_dev_name)267			return -ENOMEM;268	}269	list_add_tail(&tc->node, &cti_dev->trig_cons);270	cti_dev->nr_trig_con++;271 272	/* add connection usage bit info to overall info */273	drvdata->config.trig_in_use |= tc->con_in->used_mask;274	drvdata->config.trig_out_use |= tc->con_out->used_mask;275 276	return 0;277}278 279/* create a trigger connection with appropriately sized signal groups */280struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,281					   int out_sigs)282{283	struct cti_trig_con *tc = NULL;284	struct cti_trig_grp *in = NULL, *out = NULL;285 286	tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL);287	if (!tc)288		return tc;289 290	in = devm_kzalloc(dev,291			  offsetof(struct cti_trig_grp, sig_types[in_sigs]),292			  GFP_KERNEL);293	if (!in)294		return NULL;295 296	out = devm_kzalloc(dev,297			   offsetof(struct cti_trig_grp, sig_types[out_sigs]),298			   GFP_KERNEL);299	if (!out)300		return NULL;301 302	tc->con_in = in;303	tc->con_out = out;304	tc->con_in->nr_sigs = in_sigs;305	tc->con_out->nr_sigs = out_sigs;306	return tc;307}308 309/*310 * Add a default connection if nothing else is specified.311 * single connection based on max in/out info, no assoc device312 */313int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)314{315	int ret = 0;316	int n_trigs = drvdata->config.nr_trig_max;317	u32 n_trig_mask = GENMASK(n_trigs - 1, 0);318	struct cti_trig_con *tc = NULL;319 320	/*321	 * Assume max trigs for in and out,322	 * all used, default sig types allocated323	 */324	tc = cti_allocate_trig_con(dev, n_trigs, n_trigs);325	if (!tc)326		return -ENOMEM;327 328	tc->con_in->used_mask = n_trig_mask;329	tc->con_out->used_mask = n_trig_mask;330	ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default");331	return ret;332}333 334/** cti channel api **/335/* attach/detach channel from trigger - write through if enabled. */336int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,337			enum cti_trig_dir direction, u32 channel_idx,338			u32 trigger_idx)339{340	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);341	struct cti_config *config = &drvdata->config;342	u32 trig_bitmask;343	u32 chan_bitmask;344	u32 reg_value;345	int reg_offset;346 347	/* ensure indexes in range */348	if ((channel_idx >= config->nr_ctm_channels) ||349	   (trigger_idx >= config->nr_trig_max))350		return -EINVAL;351 352	trig_bitmask = BIT(trigger_idx);353 354	/* ensure registered triggers and not out filtered */355	if (direction == CTI_TRIG_IN)	{356		if (!(trig_bitmask & config->trig_in_use))357			return -EINVAL;358	} else {359		if (!(trig_bitmask & config->trig_out_use))360			return -EINVAL;361 362		if ((config->trig_filter_enable) &&363		    (config->trig_out_filter & trig_bitmask))364			return -EINVAL;365	}366 367	/* update the local register values */368	chan_bitmask = BIT(channel_idx);369	reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :370		      CTIOUTEN(trigger_idx));371 372	spin_lock(&drvdata->spinlock);373 374	/* read - modify write - the trigger / channel enable value */375	reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :376		     config->ctiouten[trigger_idx];377	if (op == CTI_CHAN_ATTACH)378		reg_value |= chan_bitmask;379	else380		reg_value &= ~chan_bitmask;381 382	/* write local copy */383	if (direction == CTI_TRIG_IN)384		config->ctiinen[trigger_idx] = reg_value;385	else386		config->ctiouten[trigger_idx] = reg_value;387 388	/* write through if enabled */389	if (cti_active(config))390		cti_write_single_reg(drvdata, reg_offset, reg_value);391	spin_unlock(&drvdata->spinlock);392	return 0;393}394 395int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,396			u32 channel_idx)397{398	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);399	struct cti_config *config = &drvdata->config;400	u32 chan_bitmask;401	u32 reg_value;402	int err = 0;403 404	if (channel_idx >= config->nr_ctm_channels)405		return -EINVAL;406 407	chan_bitmask = BIT(channel_idx);408 409	spin_lock(&drvdata->spinlock);410	reg_value = config->ctigate;411	switch (op) {412	case CTI_GATE_CHAN_ENABLE:413		reg_value |= chan_bitmask;414		break;415 416	case CTI_GATE_CHAN_DISABLE:417		reg_value &= ~chan_bitmask;418		break;419 420	default:421		err = -EINVAL;422		break;423	}424	if (err == 0) {425		config->ctigate = reg_value;426		if (cti_active(config))427			cti_write_single_reg(drvdata, CTIGATE, reg_value);428	}429	spin_unlock(&drvdata->spinlock);430	return err;431}432 433int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,434		      u32 channel_idx)435{436	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);437	struct cti_config *config = &drvdata->config;438	u32 chan_bitmask;439	u32 reg_value;440	u32 reg_offset;441	int err = 0;442 443	if (channel_idx >= config->nr_ctm_channels)444		return -EINVAL;445 446	chan_bitmask = BIT(channel_idx);447 448	spin_lock(&drvdata->spinlock);449	reg_value = config->ctiappset;450	switch (op) {451	case CTI_CHAN_SET:452		config->ctiappset |= chan_bitmask;453		reg_value  = config->ctiappset;454		reg_offset = CTIAPPSET;455		break;456 457	case CTI_CHAN_CLR:458		config->ctiappset &= ~chan_bitmask;459		reg_value = chan_bitmask;460		reg_offset = CTIAPPCLEAR;461		break;462 463	case CTI_CHAN_PULSE:464		config->ctiappset &= ~chan_bitmask;465		reg_value = chan_bitmask;466		reg_offset = CTIAPPPULSE;467		break;468 469	default:470		err = -EINVAL;471		break;472	}473 474	if ((err == 0) && cti_active(config))475		cti_write_single_reg(drvdata, reg_offset, reg_value);476	spin_unlock(&drvdata->spinlock);477 478	return err;479}480 481static bool cti_add_sysfs_link(struct cti_drvdata *drvdata,482			       struct cti_trig_con *tc)483{484	struct coresight_sysfs_link link_info;485	int link_err = 0;486 487	link_info.orig = drvdata->csdev;488	link_info.orig_name = tc->con_dev_name;489	link_info.target = tc->con_dev;490	link_info.target_name = dev_name(&drvdata->csdev->dev);491 492	link_err = coresight_add_sysfs_link(&link_info);493	if (link_err)494		dev_warn(&drvdata->csdev->dev,495			 "Failed to set CTI sysfs link %s<=>%s\n",496			 link_info.orig_name, link_info.target_name);497	return !link_err;498}499 500static void cti_remove_sysfs_link(struct cti_drvdata *drvdata,501				  struct cti_trig_con *tc)502{503	struct coresight_sysfs_link link_info;504 505	link_info.orig = drvdata->csdev;506	link_info.orig_name = tc->con_dev_name;507	link_info.target = tc->con_dev;508	link_info.target_name = dev_name(&drvdata->csdev->dev);509	coresight_remove_sysfs_link(&link_info);510}511 512/*513 * Look for a matching connection device name in the list of connections.514 * If found then swap in the csdev name, set trig con association pointer515 * and return found.516 */517static bool518cti_match_fixup_csdev(struct cti_device *ctidev, const char *node_name,519		      struct coresight_device *csdev)520{521	struct cti_trig_con *tc;522	struct cti_drvdata *drvdata = container_of(ctidev, struct cti_drvdata,523						   ctidev);524 525	list_for_each_entry(tc, &ctidev->trig_cons, node) {526		if (tc->con_dev_name) {527			if (!strcmp(node_name, tc->con_dev_name)) {528				/* match: so swap in csdev name & dev */529				tc->con_dev_name = dev_name(&csdev->dev);530				tc->con_dev = csdev;531				/* try to set sysfs link */532				if (cti_add_sysfs_link(drvdata, tc))533					return true;534				/* link failed - remove CTI reference */535				tc->con_dev = NULL;536				break;537			}538		}539	}540	return false;541}542 543/*544 * Search the cti list to add an associated CTI into the supplied CS device545 * This will set the association if CTI declared before the CS device.546 * (called from coresight_register() without coresight_mutex locked).547 */548static void cti_add_assoc_to_csdev(struct coresight_device *csdev)549{550	struct cti_drvdata *ect_item;551	struct cti_device *ctidev;552	const char *node_name = NULL;553 554	/* protect the list */555	mutex_lock(&ect_mutex);556 557	/* exit if current is an ECT device.*/558	if ((csdev->type == CORESIGHT_DEV_TYPE_HELPER &&559	     csdev->subtype.helper_subtype ==560		     CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI) ||561	    list_empty(&ect_net))562		goto cti_add_done;563 564	/* if we didn't find the csdev previously we used the fwnode name */565	node_name = cti_plat_get_node_name(dev_fwnode(csdev->dev.parent));566	if (!node_name)567		goto cti_add_done;568 569	/* for each CTI in list... */570	list_for_each_entry(ect_item, &ect_net, node) {571		ctidev = &ect_item->ctidev;572		if (cti_match_fixup_csdev(ctidev, node_name, csdev)) {573			/*574			 * if we found a matching csdev then update the ECT575			 * association pointer for the device with this CTI.576			 */577			coresight_add_helper(csdev, ect_item->csdev);578			break;579		}580	}581cti_add_done:582	mutex_unlock(&ect_mutex);583}584 585/*586 * Removing the associated devices is easier.587 */588static void cti_remove_assoc_from_csdev(struct coresight_device *csdev)589{590	struct cti_drvdata *ctidrv;591	struct cti_trig_con *tc;592	struct cti_device *ctidev;593	union coresight_dev_subtype cti_subtype = {594		.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI595	};596	struct coresight_device *cti_csdev = coresight_find_output_type(597		csdev->pdata, CORESIGHT_DEV_TYPE_HELPER, cti_subtype);598 599	if (!cti_csdev)600		return;601 602	mutex_lock(&ect_mutex);603	ctidrv = csdev_to_cti_drvdata(cti_csdev);604	ctidev = &ctidrv->ctidev;605	list_for_each_entry(tc, &ctidev->trig_cons, node) {606		if (tc->con_dev == csdev) {607			cti_remove_sysfs_link(ctidrv, tc);608			tc->con_dev = NULL;609			break;610		}611	}612	mutex_unlock(&ect_mutex);613}614 615/*616 * Operations to add and remove associated CTI.617 * Register to coresight core driver as call back function.618 */619static struct cti_assoc_op cti_assoc_ops = {620	.add = cti_add_assoc_to_csdev,621	.remove = cti_remove_assoc_from_csdev622};623 624/*625 * Update the cross references where the associated device was found626 * while we were building the connection info. This will occur if the627 * assoc device was registered before the CTI.628 */629static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)630{631	struct cti_trig_con *tc;632	struct cti_device *ctidev = &drvdata->ctidev;633 634	list_for_each_entry(tc, &ctidev->trig_cons, node) {635		if (tc->con_dev) {636			/* if we can set the sysfs link */637			if (cti_add_sysfs_link(drvdata, tc))638				/* set the CTI/csdev association */639				coresight_add_helper(tc->con_dev,640						     drvdata->csdev);641			else642				/* otherwise remove reference from CTI */643				tc->con_dev = NULL;644		}645	}646}647 648static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata)649{650	struct cti_trig_con *tc;651	struct cti_device *ctidev = &drvdata->ctidev;652 653	list_for_each_entry(tc, &ctidev->trig_cons, node) {654		if (tc->con_dev) {655			cti_remove_sysfs_link(drvdata, tc);656			tc->con_dev = NULL;657		}658	}659}660 661/** cti PM callbacks **/662static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,663			     void *v)664{665	struct cti_drvdata *drvdata;666	struct coresight_device *csdev;667	unsigned int cpu = smp_processor_id();668	int notify_res = NOTIFY_OK;669 670	if (!cti_cpu_drvdata[cpu])671		return NOTIFY_OK;672 673	drvdata = cti_cpu_drvdata[cpu];674	csdev = drvdata->csdev;675 676	if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))677		return NOTIFY_BAD;678 679	spin_lock(&drvdata->spinlock);680 681	switch (cmd) {682	case CPU_PM_ENTER:683		/* CTI regs all static - we have a copy & nothing to save */684		drvdata->config.hw_powered = false;685		if (drvdata->config.hw_enabled)686			coresight_disclaim_device(csdev);687		break;688 689	case CPU_PM_ENTER_FAILED:690		drvdata->config.hw_powered = true;691		if (drvdata->config.hw_enabled) {692			if (coresight_claim_device(csdev))693				drvdata->config.hw_enabled = false;694		}695		break;696 697	case CPU_PM_EXIT:698		/* write hardware registers to re-enable. */699		drvdata->config.hw_powered = true;700		drvdata->config.hw_enabled = false;701 702		/* check enable reference count to enable HW */703		if (drvdata->config.enable_req_count) {704			/* check we can claim the device as we re-power */705			if (coresight_claim_device(csdev))706				goto cti_notify_exit;707 708			drvdata->config.hw_enabled = true;709			cti_write_all_hw_regs(drvdata);710		}711		break;712 713	default:714		notify_res = NOTIFY_DONE;715		break;716	}717 718cti_notify_exit:719	spin_unlock(&drvdata->spinlock);720	return notify_res;721}722 723static struct notifier_block cti_cpu_pm_nb = {724	.notifier_call = cti_cpu_pm_notify,725};726 727/* CPU HP handlers */728static int cti_starting_cpu(unsigned int cpu)729{730	struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];731 732	if (!drvdata)733		return 0;734 735	cti_cpuhp_enable_hw(drvdata);736	return 0;737}738 739static int cti_dying_cpu(unsigned int cpu)740{741	struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];742 743	if (!drvdata)744		return 0;745 746	spin_lock(&drvdata->spinlock);747	drvdata->config.hw_powered = false;748	if (drvdata->config.hw_enabled)749		coresight_disclaim_device(drvdata->csdev);750	spin_unlock(&drvdata->spinlock);751	return 0;752}753 754static int cti_pm_setup(struct cti_drvdata *drvdata)755{756	int ret;757 758	if (drvdata->ctidev.cpu == -1)759		return 0;760 761	if (nr_cti_cpu)762		goto done;763 764	cpus_read_lock();765	ret = cpuhp_setup_state_nocalls_cpuslocked(766			CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,767			"arm/coresight_cti:starting",768			cti_starting_cpu, cti_dying_cpu);769	if (ret) {770		cpus_read_unlock();771		return ret;772	}773 774	ret = cpu_pm_register_notifier(&cti_cpu_pm_nb);775	cpus_read_unlock();776	if (ret) {777		cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);778		return ret;779	}780 781done:782	nr_cti_cpu++;783	cti_cpu_drvdata[drvdata->ctidev.cpu] = drvdata;784 785	return 0;786}787 788/* release PM registrations */789static void cti_pm_release(struct cti_drvdata *drvdata)790{791	if (drvdata->ctidev.cpu == -1)792		return;793 794	cti_cpu_drvdata[drvdata->ctidev.cpu] = NULL;795	if (--nr_cti_cpu == 0) {796		cpu_pm_unregister_notifier(&cti_cpu_pm_nb);797		cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);798	}799}800 801/** cti ect operations **/802int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)803{804	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);805 806	return cti_enable_hw(drvdata);807}808 809int cti_disable(struct coresight_device *csdev, void *data)810{811	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);812 813	return cti_disable_hw(drvdata);814}815 816static const struct coresight_ops_helper cti_ops_ect = {817	.enable = cti_enable,818	.disable = cti_disable,819};820 821static const struct coresight_ops cti_ops = {822	.helper_ops = &cti_ops_ect,823};824 825/*826 * Free up CTI specific resources827 * called by dev->release, need to call down to underlying csdev release.828 */829static void cti_device_release(struct device *dev)830{831	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);832	struct cti_drvdata *ect_item, *ect_tmp;833 834	mutex_lock(&ect_mutex);835	cti_pm_release(drvdata);836 837	/* remove from the list */838	list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {839		if (ect_item == drvdata) {840			list_del(&ect_item->node);841			break;842		}843	}844	mutex_unlock(&ect_mutex);845 846	if (drvdata->csdev_release)847		drvdata->csdev_release(dev);848}849static void cti_remove(struct amba_device *adev)850{851	struct cti_drvdata *drvdata = dev_get_drvdata(&adev->dev);852 853	mutex_lock(&ect_mutex);854	cti_remove_conn_xrefs(drvdata);855	mutex_unlock(&ect_mutex);856 857	coresight_unregister(drvdata->csdev);858}859 860static int cti_probe(struct amba_device *adev, const struct amba_id *id)861{862	int ret = 0;863	void __iomem *base;864	struct device *dev = &adev->dev;865	struct cti_drvdata *drvdata = NULL;866	struct coresight_desc cti_desc;867	struct coresight_platform_data *pdata = NULL;868	struct resource *res = &adev->res;869 870	/* driver data*/871	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);872	if (!drvdata)873		return -ENOMEM;874 875	/* Validity for the resource is already checked by the AMBA core */876	base = devm_ioremap_resource(dev, res);877	if (IS_ERR(base))878		return PTR_ERR(base);879 880	drvdata->base = base;881	cti_desc.access = CSDEV_ACCESS_IOMEM(base);882 883	dev_set_drvdata(dev, drvdata);884 885	/* default CTI device info  */886	drvdata->ctidev.cpu = -1;887	drvdata->ctidev.nr_trig_con = 0;888	drvdata->ctidev.ctm_id = 0;889	INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);890 891	spin_lock_init(&drvdata->spinlock);892 893	/* initialise CTI driver config values */894	cti_set_default_config(dev, drvdata);895 896	pdata = coresight_cti_get_platform_data(dev);897	if (IS_ERR(pdata)) {898		dev_err(dev, "coresight_cti_get_platform_data err\n");899		return  PTR_ERR(pdata);900	}901 902	/* default to powered - could change on PM notifications */903	drvdata->config.hw_powered = true;904 905	/* set up device name - will depend if cpu bound or otherwise */906	if (drvdata->ctidev.cpu >= 0)907		cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",908					       drvdata->ctidev.cpu);909	else910		cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);911	if (!cti_desc.name)912		return -ENOMEM;913 914	/* setup CPU power management handling for CPU bound CTI devices. */915	ret = cti_pm_setup(drvdata);916	if (ret)917		return ret;918 919	/* create dynamic attributes for connections */920	ret = cti_create_cons_sysfs(dev, drvdata);921	if (ret) {922		dev_err(dev, "%s: create dynamic sysfs entries failed\n",923			cti_desc.name);924		goto pm_release;925	}926 927	/* set up coresight component description */928	cti_desc.pdata = pdata;929	cti_desc.type = CORESIGHT_DEV_TYPE_HELPER;930	cti_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI;931	cti_desc.ops = &cti_ops;932	cti_desc.groups = drvdata->ctidev.con_groups;933	cti_desc.dev = dev;934	drvdata->csdev = coresight_register(&cti_desc);935	if (IS_ERR(drvdata->csdev)) {936		ret = PTR_ERR(drvdata->csdev);937		goto pm_release;938	}939 940	/* add to list of CTI devices */941	mutex_lock(&ect_mutex);942	list_add(&drvdata->node, &ect_net);943	/* set any cross references */944	cti_update_conn_xrefs(drvdata);945	mutex_unlock(&ect_mutex);946 947	/* set up release chain */948	drvdata->csdev_release = drvdata->csdev->dev.release;949	drvdata->csdev->dev.release = cti_device_release;950 951	/* all done - dec pm refcount */952	pm_runtime_put(&adev->dev);953	dev_info(&drvdata->csdev->dev, "CTI initialized\n");954	return 0;955 956pm_release:957	cti_pm_release(drvdata);958	return ret;959}960 961static struct amba_cs_uci_id uci_id_cti[] = {962	{963		/*  CTI UCI data */964		.devarch	= 0x47701a14, /* CTI v2 */965		.devarch_mask	= 0xfff0ffff,966		.devtype	= 0x00000014, /* maj(0x4-debug) min(0x1-ECT) */967	}968};969 970static const struct amba_id cti_ids[] = {971	CS_AMBA_ID(0x000bb906), /* Coresight CTI (SoC 400), C-A72, C-A57 */972	CS_AMBA_ID(0x000bb922), /* CTI - C-A8 */973	CS_AMBA_ID(0x000bb9a8), /* CTI - C-A53 */974	CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */975	CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */976	CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */977	{ 0, 0, NULL },978};979 980MODULE_DEVICE_TABLE(amba, cti_ids);981 982static struct amba_driver cti_driver = {983	.drv = {984		.name	= "coresight-cti",985		.suppress_bind_attrs = true,986	},987	.probe		= cti_probe,988	.remove		= cti_remove,989	.id_table	= cti_ids,990};991 992static int __init cti_init(void)993{994	int ret;995 996	ret = amba_driver_register(&cti_driver);997	if (ret)998		pr_info("Error registering cti driver\n");999	coresight_set_cti_ops(&cti_assoc_ops);1000	return ret;1001}1002 1003static void __exit cti_exit(void)1004{1005	coresight_remove_cti_ops();1006	amba_driver_unregister(&cti_driver);1007}1008 1009module_init(cti_init);1010module_exit(cti_exit);1011 1012MODULE_AUTHOR("Mike Leach <mike.leach@linaro.org>");1013MODULE_DESCRIPTION("Arm CoreSight CTI Driver");1014MODULE_LICENSE("GPL v2");1015