static int stm_xfer_start(void)
{
	struct stm_dev *stm = _dev_stm;
	struct stm_ctrl *stm_ctrl;
	u32 reg_word;

	if (!stm)
		return -ENODEV;

	/* REVERTME : filter PUNIT and SCU MasterID when switching to USB */
	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_ANNIEDALE) {
		pr_info("%s\n REVERTME : filter PUNIT and SCU MasterID\n", __func__);
		reg_word = stm_readl(stm->stm_ioaddr, (u32)STM_MASMSK1);
		reg_word |= 0x28;
		stm_writel(stm->stm_ioaddr, (u32)STM_MASMSK1, reg_word);

		pr_info("%s\n REVERTME : USBTO\n", __func__);
		reg_word = stm_readl(stm->stm_ioaddr, (u32)STM_USBTO);
		reg_word |= 0x01;
		stm_writel(stm->stm_ioaddr, (u32)STM_USBTO, reg_word);
	}

	stm_ctrl = &stm->stm_ctrl_hwreg;
	stm_ctrl->reg_word = stm_readl(stm->stm_ioaddr, (u32)STM_CTRL);

	stm_ctrl->usb_debug_en = true;
	stm_ctrl->pti_out_en = false;

	stm_writel(stm->stm_ioaddr, (u32)STM_CTRL, stm_ctrl->reg_word);
	pr_info("%s\n switch STM output to DvC.Trace ", __func__);

	return 0;
}
static int stm_hwevent_isenable(struct stm_drvdata *drvdata)
{
	int ret = 0;

	spin_lock(&drvdata->spinlock);
	if (drvdata->enable)
		if (BVAL(stm_readl(drvdata, STMHEMCR), 0))
			ret = stm_readl(drvdata, STMHEER) == 0 ? 0 : 1;
	spin_unlock(&drvdata->spinlock);

	return ret;
}
static void __stm_enable(struct stm_drvdata *drvdata)
{
	__stm_hwevent_enable(drvdata);
	__stm_port_enable(drvdata);

	STM_UNLOCK(drvdata);

	stm_writel(drvdata, 0xFFF, STMSYNCR);
	/* SYNCEN is read-only and HWTEN is not implemented */
	stm_writel(drvdata, 0x100003,STMTCSR);

#ifdef	STM_DEBUG
	dev_dbg("STMSYNCR = 0x%02x\n", stm_readl(drvdata, STMSYNCR));
	dev_dbg("STMTCSR = 0x%02x\n", stm_readl(drvdata, STMTCSR));
#endif

	STM_LOCK(drvdata);
}
static void __stm_port_enable(struct stm_drvdata *drvdata)
{
	STM_UNLOCK(drvdata);

	stm_writel(drvdata, 0x10, STMSPTRIGCSR);
	stm_writel(drvdata, 0xFFFFFFFF, STMSPER);

	stm_writel(drvdata,0x0FFF8000,STMSPSCR);
	stm_writel(drvdata,0xFFFFC000,STMSPMSCR);

#ifdef	STM_DEBUG
	dev_dbg("STMSPTRIGCSR = 0x%02x\n", stm_readl(drvdata, STMSPTRIGCSR));
	dev_dbg("STMSPER = 0x%02x\n", stm_readl(drvdata, STMSPER));
	dev_dbg("STMSPSCR = 0x%02x\n", stm_readl(drvdata, STMSPSCR));
	dev_dbg("STMSPMSCR = 0x%02x\n", stm_readl(drvdata, STMSPMSCR));
#endif
	STM_LOCK(drvdata);
}
static void __stm_hwevent_enable(struct stm_drvdata *drvdata)
{
	STM_UNLOCK(drvdata);

	/* Program STMHETER to ensure TRIGOUTHETE (fed to CTI) is asserted
	   for HW events.
	*/
	stm_writel(drvdata, 0xFFFFFFFF, STMHETER);
	stm_writel(drvdata, 0xFFFFFFFF, STMHEER);
	stm_writel(drvdata, 0x5, STMHEMCR);

#ifdef	STM_DEBUG
	dev_dbg("STMHETER = 0x%02x\n", stm_readl(drvdata, STMHETER));
	dev_dbg("STMHEER = 0x%02x\n", stm_readl(drvdata, STMHEER));
	dev_dbg("STMHEMCR = 0x%02x\n", stm_readl(drvdata, STMHEMCR));
#endif

	STM_LOCK(drvdata);
}
static int stm_port_isenable(struct stm_drvdata *drvdata)
{
	int ret = 0;

	spin_lock(&drvdata->spinlock);
	if (drvdata->enable)
		ret = stm_readl(drvdata, STMSPER) == 0 ? 0 : 1;
	spin_unlock(&drvdata->spinlock);

	return ret;
}
/**
 * stm_init() - initialize stmsub3dbgthr register
 *
 * @return - 0 on Success
 */
static int stm_init(void)
{
	struct stm_dev *stm = _dev_stm;
	struct stm_usb3_ctrl *usb3dbg;

	if (!stm)
		return -ENODEV;

	usb3dbg = &stm->stm_usb3_hwreg;
	usb3dbg->reg_word = stm_readl(stm->stm_ioaddr, (u32)STM_USB3DBGGTHR);

	usb3dbg->reg_word = 0xFF;

	stm_writel(stm->stm_ioaddr, (u32)STM_USB3DBGGTHR, usb3dbg->reg_word);

	return 0;
}
/**
 * stm_kernel_set_out()-
 * Kernel API function used to
 * set STM output configuration to PTI or USB.
 *
 * @bus_type:
 *	0 = PTI 4-bits legacy end user
 *	1 = PTI 4-bits NiDnT
 *	2 = PTI 16-bits
 *	3 = PTI 12-bits
 *	4 = PTI 8-bits
 *	15 = USB Debug-Class (DvC.Trace)
 *
 */
int stm_kernel_set_out(int bus_type)
{

	struct stm_dev *drv_stm = _dev_stm;

	/*
	 * since this function is exported, this is treated like an
	 * API function, thus, all parameters should
	 * be checked for validity.
	 */
	if (drv_stm == NULL)
		return 0;

	mutex_lock(&stmlock);

	drv_stm->stm_ctrl_hwreg.reg_word =
		stm_readl(drv_stm->stm_ioaddr, (u32)STM_CTRL);

	switch (bus_type) {
	case STM_PTI_4BIT_LEGACY:
	case STM_PTI_4BIT_NIDNT:
	case STM_PTI_16BIT:
	case STM_PTI_12BIT:
	case STM_PTI_8BIT:
		drv_stm->stm_ctrl_hwreg.pti_out_en = true;
		drv_stm->stm_ctrl_hwreg.usb_debug_en = false;
		drv_stm->stm_ctrl_hwreg.pti_out_mode_sel = bus_type;
		stm_writel(drv_stm->stm_ioaddr, (u32)STM_CTRL,
			   drv_stm->stm_ctrl_hwreg.reg_word);
		break;
	case STM_USB:
		drv_stm->stm_ctrl_hwreg.pti_out_en = false;
		drv_stm->stm_ctrl_hwreg.usb_debug_en = true;
		stm_writel(drv_stm->stm_ioaddr, (u32)STM_CTRL,
			   drv_stm->stm_ctrl_hwreg.reg_word);
		break;
	default:
		/* N/A */
		break;
	}
	mutex_unlock(&stmlock);

	return 1;
}
static int stm_xfer_stop(void)
{
	struct stm_dev *stm = _dev_stm;
	struct stm_ctrl *stm_ctrl;

	if (!stm)
		return -ENODEV;

	stm_ctrl = &stm->stm_ctrl_hwreg;
	stm_ctrl->reg_word = stm_readl(stm->stm_ioaddr, (u32)STM_CTRL);

	stm_ctrl->usb_debug_en = false;
	stm_ctrl->pti_out_en = true;

	stm_writel(stm->stm_ioaddr, (u32)STM_CTRL, stm_ctrl->reg_word);
	pr_info("%s\n switch STM to 4bits MIPI PTI (default)", __func__);

	return 0;
}
/**
 * stm_kernel_get_out()-
 * Kernel API function used to get
 * STM output cofiguration PTI or USB.
 *
 */
int stm_kernel_get_out(void)
{
	struct stm_dev *drv_stm = _dev_stm;
	int ret = -EOPNOTSUPP;

	if (drv_stm == NULL)
		return -EOPNOTSUPP;

	mutex_lock(&stmlock);

	drv_stm->stm_ctrl_hwreg.reg_word =
		stm_readl(drv_stm->stm_ioaddr, (u32)STM_CTRL);

	if (!drv_stm->stm_ctrl_hwreg.usb_debug_en) {
		if (drv_stm->stm_ctrl_hwreg.pti_out_en)
			ret = (int)drv_stm->stm_ctrl_hwreg.pti_out_mode_sel;
	} else {
		ret = (int)STM_USB;
	}
	mutex_unlock(&stmlock);

	return ret;
}
/**
 * stm_dev_init()- Used to setup STM resources on the pci bus.
 *
 * @pdev- pci_dev struct values for pti device.
 * @stm- stm_dev struct managing stm resources
 *
 * Returns:
 *	0 for success
 *	otherwise, error
 */
int stm_dev_init(struct pci_dev *pdev,
		 struct stm_dev *stm)
{
	int retval = 0;
	int pci_bar = 0;

	if (!cpu_has_debug_feature(DEBUG_FEATURE_PTI))
		return -ENODEV;

	dev_dbg(&pdev->dev, "%s %s(%d): STM PCI ID %04x:%04x\n", __FILE__,
		__func__, __LINE__, pdev->vendor, pdev->device);

	stm->stm_addr = pci_resource_start(pdev, pci_bar);

	retval = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
	if (retval != 0) {
		dev_err(&pdev->dev,
			"%s(%d): pci_request_region() returned error %d\n",
			__func__, __LINE__, retval);
		return retval;
	}
	pr_info("stm add %x\n", stm->stm_addr);

	stm->stm_reg_base = stm->stm_addr+STM_REG_BASE;
	stm->stm_ioaddr = ioremap_nocache((u32)stm->stm_reg_base,
					  STM_REG_LEN);
	if (!stm->stm_ioaddr) {
		retval = -ENOMEM;
		goto out_release_region;
	}

	stm->stm_trb_base = stm->stm_addr+STM_TRB_BASE;
	stm->trb_ioaddr = ioremap_nocache((u32)stm->stm_trb_base,
					  STM_TRB_LEN);
	if (!stm->trb_ioaddr) {
		retval = -ENOMEM;
		goto out_iounmap_stm_ioaddr;
	}

	stm->stm_ctrl_hwreg.reg_word = stm_readl(stm->stm_ioaddr,
						 (u32)STM_CTRL);
	stm->stm_usb3_hwreg.reg_word = stm_readl(stm->stm_ioaddr,
						 (u32)STM_USB3DBGGTHR);

	_dev_stm = stm;

	dwc3_register_io_ebc(&stm_ebc_io_ops);
	dwc3_register_io_ebc(&exi_in_ebc_io_ops);
	dwc3_register_io_ebc(&exi_out_ebc_io_ops);

	pr_info("successfully registered ebc io ops\n");

	return retval;

out_iounmap_stm_ioaddr:
	pci_iounmap(pdev, stm->stm_ioaddr);

out_release_region:
	pci_release_region(pdev, pci_bar);

	_dev_stm = NULL;
	return retval;

}