static int __tpiu_enable_to_sdc_swdtrc(struct tpiu_drvdata *drvdata)
{
	int ret;

	/*
	 * Vote for clk on since tracing may or may not be enabled in
	 * swdtrc mode and hence the clk is not guaranteed to be enabled.
	 */
	ret = clk_prepare_enable(drvdata->clk);
	if (ret)
		return ret;

	ret = __tpiu_enable_to_sdc(drvdata);
	if (ret)
		goto err;

	/*
	 * Required sequence to prevent SRST asserstion: set trace to
	 * continuous mode followed by setting ETM MODE to 1 before switching
	 * to swd.
	 */
	__tpiu_enable(drvdata, 0x2, 0x103);

	msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);

	/* Pull down sdc cmd line */
	msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x96D);
	msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 3);
err:
	return ret;
}
static int tpiu_enable(struct coresight_device *csdev)
{
	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
	int ret;

	ret = clk_prepare_enable(drvdata->clk);
	if (ret)
		return ret;

	mutex_lock(&drvdata->mutex);

	if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
		ret = __tpiu_enable_to_mictor(drvdata);
	else
		ret = __tpiu_enable_to_sdc(drvdata);
	if (ret)
		goto err;
	drvdata->enable = true;

	mutex_unlock(&drvdata->mutex);

	dev_info(drvdata->dev, "TPIU enabled\n");
	return 0;
err:
	mutex_unlock(&drvdata->mutex);
	clk_disable_unprepare(drvdata->clk);
	return ret;
}
static ssize_t tpiu_store_out_mode(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t size)
{
	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
	char str[10] = "";
	int ret;

	if (strlen(buf) >= 10)
		return -EINVAL;
	if (sscanf(buf, "%s", str) != 1)
		return -EINVAL;

	mutex_lock(&drvdata->mutex);
	if (!strcmp(str, "mictor")) {
		if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
			goto out;

		if (!drvdata->enable) {
			drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
			goto out;
		}
		__tpiu_disable_to_sdc(drvdata);
		ret = __tpiu_enable_to_mictor(drvdata);
		if (ret) {
			dev_err(drvdata->dev, "failed to enable mictor\n");
			goto err;
		}
		drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
	} else if (!strcmp(str, "sdc")) {
		if (drvdata->out_mode == TPIU_OUT_MODE_SDC)
			goto out;

		if (!drvdata->enable) {
			drvdata->out_mode = TPIU_OUT_MODE_SDC;
			goto out;
		}
		__tpiu_disable_to_mictor(drvdata);
		ret = __tpiu_enable_to_sdc(drvdata);
		if (ret) {
			dev_err(drvdata->dev, "failed to enable sdc\n");
			goto err;
		}
		drvdata->out_mode = TPIU_OUT_MODE_SDC;
	}
out:
	mutex_unlock(&drvdata->mutex);
	return size;
err:
	mutex_unlock(&drvdata->mutex);
	return ret;
}
static int __tpiu_enable_to_sdc_trace(struct tpiu_drvdata *drvdata)
{
	int ret;

	ret = __tpiu_enable_to_sdc(drvdata);
	if (ret)
		return ret;

	__tpiu_enable(drvdata, 0x8, 0x103);

	msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
	msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
	return 0;
}