Пример #1
0
static int omap2430_runtime_resume(struct device *dev)
{
	struct omap2430_glue		*glue = dev_get_drvdata(dev);
	struct musb			*musb = glue_to_musb(glue);

	if (musb) {
		omap2430_low_level_init(musb);
		musb_writel(musb->mregs, OTG_INTERFSEL,
				musb->context.otg_interfsel);

		usb_phy_set_suspend(musb->xceiv, 0);
	}

	return 0;
}
Пример #2
0
void musb_platform_save_context(struct musb *musb,
		struct musb_context_registers *musb_context)
{
	void __iomem *musb_base = musb->mregs;
	musb_context->otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG);
	musb_context->otg_interfacesel = musb_readl(musb->mregs,
							OTG_INTERFSEL);
	if (cpu_is_omap44xx()) {
		musb_context->ctl_dev_conf = __raw_readl(ctrl_base +
							CONTROL_DEV_CONF);
		musb_context->usbotg_control = __raw_readl(ctrl_base +
							USBOTGHS_CONTROL);
	}
	musb_writel(musb_base, OTG_FORCESTDBY, 1);
}
static int musb_platform_resume(struct musb *musb)
{
	u32 l;

	if (!musb->clock)
		return 0;

	otg_set_suspend(musb->xceiv, 0);

	if (musb->set_clock)
		musb->set_clock(musb->clock, 1);
	else
		clk_enable(musb->clock);

	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
	l &= ~ENABLEWAKEUP;	/* disable wakeup */
	musb_writel(musb->mregs, OTG_SYSCONFIG, l);

	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);

	return 0;
}
static void tusb_omap_dma_release(struct dma_channel *channel)
{
	struct tusb_omap_dma_ch	*chdat = to_chdat(channel);
	struct musb		*musb = chdat->musb;
	void __iomem		*tbase = musb->ctrl_base;
	u32			reg;

	dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum, chdat->ch);

	reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
	if (chdat->tx)
		reg |= (1 << chdat->epnum);
	else
		reg |= (1 << (chdat->epnum + 15));
	musb_writel(tbase, TUSB_DMA_INT_MASK, reg);

	reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
	if (chdat->tx)
		reg |= (1 << chdat->epnum);
	else
		reg |= (1 << (chdat->epnum + 15));
	musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);

	channel->status = MUSB_DMA_STATUS_UNKNOWN;

	if (chdat->ch >= 0) {
		omap_stop_dma(chdat->ch);
		omap_free_dma(chdat->ch);
		chdat->ch = -1;
	}

	if (chdat->dmareq >= 0)
		tusb_omap_dma_free_dmareq(chdat);

	channel = NULL;
}
Пример #5
0
static int cppi_controller_stop(struct dma_controller *c)
{
	struct cppi		*controller;
	void __iomem		*tibase;
	int			i;
	struct musb		*musb;

	controller = container_of(c, struct cppi, controller);
	musb = controller->musb;

	tibase = controller->tibase;
	/* DISABLE INDIVIDUAL CHANNEL Interrupts */
	musb_writel(tibase, DAVINCI_TXCPPI_INTCLR_REG,
			DAVINCI_DMA_ALL_CHANNELS_ENABLE);
	musb_writel(tibase, DAVINCI_RXCPPI_INTCLR_REG,
			DAVINCI_DMA_ALL_CHANNELS_ENABLE);

	dev_dbg(musb->controller, "Tearing down RX and TX Channels\n");
	for (i = 0; i < ARRAY_SIZE(controller->tx); i++) {
		/* FIXME restructure of txdma to use bds like rxdma */
		controller->tx[i].last_processed = NULL;
		cppi_pool_free(controller->tx + i);
	}
	for (i = 0; i < ARRAY_SIZE(controller->rx); i++)
		cppi_pool_free(controller->rx + i);

	/* in Tx Case proper teardown is supported. We resort to disabling
	 * Tx/Rx CPPI after cleanup of Tx channels. Before TX teardown is
	 * complete TX CPPI cannot be disabled.
	 */
	/*disable tx/rx cppi */
	musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
	musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);

	return 0;
}
Пример #6
0
static void cppi41_autoreq_update(struct cppi41_channel *rx_ch, u8 autoreq)
{
	struct cppi41 *cppi = rx_ch->channel.private_data;

	if (is_host_active(cppi->musb) &&
	    autoreq != rx_ch->autoreq) {
		void *__iomem reg_base = cppi->musb->ctrl_base;
		u32 reg_val = musb_readl(reg_base, cppi->automode_reg_offs);
		u8 ep_num = rx_ch->ch_num + 1;

		reg_val &= ~USB_RX_AUTOREQ_MASK(ep_num);
		reg_val |= autoreq << USB_RX_AUTOREQ_SHIFT(ep_num);

		musb_writel(reg_base, cppi->automode_reg_offs, reg_val);
		rx_ch->autoreq = autoreq;
	}
void musb_otg_reset_usb(void){
    //reset all of the USB IP, including PHY and MAC
    unsigned int usb_reset;
    usb_reset = __raw_readl(PERICFG_BASE);
    usb_reset |= 1<<29;
    __raw_writel(usb_reset,PERICFG_BASE);
    mdelay(10);
    usb_reset &= ~(1<<29);
    __raw_writel(usb_reset,PERICFG_BASE);
    //power on the USB
    usb_phy_poweron();
    //enable interrupt
    musb_writel(mtk_musb->mregs,USB_L1INTM,0x105);
    musb_writew(mtk_musb->mregs,MUSB_INTRTXE,1);
    musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0xf7);
}
Пример #8
0
static void otg_timer(unsigned long _musb)
{
    struct musb		*musb = (void *)_musb;
    void __iomem		*mregs = musb->mregs;
    u8			devctl;
    unsigned long		flags;

    /*
     * We poll because AM35x's won't expose several OTG-critical
     * status change events (from the transceiver) otherwise.
     */
    devctl = musb_readb(mregs, MUSB_DEVCTL);
    dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
            usb_otg_state_string(musb->xceiv->state));

    spin_lock_irqsave(&musb->lock, flags);
    switch (musb->xceiv->state) {
    case OTG_STATE_A_WAIT_BCON:
        devctl &= ~MUSB_DEVCTL_SESSION;
        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);

        devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
        if (devctl & MUSB_DEVCTL_BDEVICE) {
            musb->xceiv->state = OTG_STATE_B_IDLE;
            MUSB_DEV_MODE(musb);
        } else {
            musb->xceiv->state = OTG_STATE_A_IDLE;
            MUSB_HST_MODE(musb);
        }
        break;
    case OTG_STATE_A_WAIT_VFALL:
        musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
        musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG,
                    MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
        break;
    case OTG_STATE_B_IDLE:
        devctl = musb_readb(mregs, MUSB_DEVCTL);
        if (devctl & MUSB_DEVCTL_BDEVICE)
            mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
        else
            musb->xceiv->state = OTG_STATE_A_IDLE;
        break;
    default:
        break;
    }
    spin_unlock_irqrestore(&musb->lock, flags);
}
Пример #9
0
int __init musb_platform_init(struct musb *musb)
{
	void __iomem	*tibase = musb->ctrl_base;
	u32		revision;

	musb->mregs += DAVINCI_BASE_OFFSET;
#if 0
	/* REVISIT there's something odd about clocking, this
	 * didn't appear do the job ...
	 */
	musb->clock = clk_get(pDevice, "usb");
	if (IS_ERR(musb->clock))
		return PTR_ERR(musb->clock);

	status = clk_enable(musb->clock);
	if (status < 0)
		return -ENODEV;
#endif

	/* returns zero if e.g. not clocked */
	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
	if (revision == 0)
		return -ENODEV;

	if (is_host_enabled(musb))
		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);

	musb->board_set_vbus = davinci_set_vbus;
	davinci_source_power(musb, 0, 1);

	/* reset the controller */
	musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);

	/* start the on-chip PHY and its PLL */
	phy_on();

	msleep(5);

	/* NOTE:  irqs are in mixed mode, not bypass to pure-musb */
	pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
		revision, __raw_readl((void __force __iomem *)
				IO_ADDRESS(USBPHY_CTL_PADDR)),
		musb_readb(tibase, DAVINCI_USB_CTRL_REG));

	musb->isr = davinci_interrupt;
	return 0;
}
static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel,
		unsigned mode)
{
	struct cppi41_dma_controller *controller = cppi41_channel->controller;
	u32 port;
	u32 new_mode;
	u32 old_mode;

	old_mode = controller->auto_req;
	port = cppi41_channel->port_num;
	new_mode = update_ep_mode(port, mode, old_mode);

	if (new_mode == old_mode)
		return;
	controller->auto_req = new_mode;
	musb_writel(controller->musb->ctrl_base, USB_CTRL_AUTOREQ, new_mode);
}
Пример #11
0
static int omap2430_runtime_resume(struct device *dev)
{
	struct omap2430_glue		*glue = dev_get_drvdata(dev);
	struct musb			*musb = glue_to_musb(glue);

	if (!musb)
		return 0;

	phy_init(musb->phy);
	phy_power_on(musb->phy);

	omap2430_low_level_init(musb);
	musb_writel(musb->mregs, OTG_INTERFSEL,
		    musb->context.otg_interfsel);

	return 0;
}
Пример #12
0
static int am35x_musb_init(struct musb *musb)
{
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;
	void __iomem *reg_base = musb->ctrl_base;
	u32 rev;

	musb->mregs += USB_MENTOR_CORE_OFFSET;

	/* Returns zero if e.g. not clocked */
	rev = musb_readl(reg_base, USB_REVISION_REG);
	if (!rev)
		return -ENODEV;

	usb_nop_xceiv_register();
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv)
		return -ENODEV;

	if (is_host_enabled(musb))
		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);

	/* Reset the musb */
	if (data->reset)
		data->reset();

	/* Reset the controller */
	musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);

	/* Start the on-chip PHY and its PLL. */
	if (data->set_phy_power)
		data->set_phy_power(1);

	msleep(5);

	musb->isr = am35x_musb_interrupt;

	/* clear level interrupt */
	if (data->clear_irq)
		data->clear_irq();

	return 0;
}
Пример #13
0
/*
 * Allocate dmareq0 to the current channel unless it's already taken
 */
static inline int tusb_omap_use_shared_dmareq(struct tusb_omap_dma_ch *chdat)
{
	u32		reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);

	if (reg != 0) {
		dev_dbg(chdat->musb->controller, "ep%i dmareq0 is busy for ep%i\n",
			chdat->epnum, reg & 0xf);
		return -EAGAIN;
	}

	if (chdat->tx)
		reg = (1 << 4) | chdat->epnum;
	else
		reg = chdat->epnum;

	musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);

	return 0;
}
Пример #14
0
/* Context: controller irqlocked */
static inline void
cppi_rndis_update(struct cppi_channel *c, int is_rx,
		void __iomem *tibase, int is_rndis)
{
	/* we may need to change the rndis flag for this cppi channel */
	if (c->is_rndis != is_rndis) {
		u32	value = musb_readl(tibase, DAVINCI_RNDIS_REG);
		u32	temp = 1 << (c->index);

		if (is_rx)
			temp <<= 16;
		if (is_rndis)
			value |= temp;
		else
			value &= ~temp;
		musb_writel(tibase, DAVINCI_RNDIS_REG, value);
		c->is_rndis = is_rndis;
	}
}
Пример #15
0
void static otg_int_init(void)
{
#ifdef ID_PIN_USE_EX_EINT
	mt_set_gpio_mode(GPIO_OTG_IDDIG_EINT_PIN, GPIO_OTG_IDDIG_EINT_PIN_M_USB_IDDIG);
	mt_set_gpio_dir(GPIO_OTG_IDDIG_EINT_PIN, GPIO_DIR_IN);
	mt_set_gpio_pull_enable(GPIO_OTG_IDDIG_EINT_PIN, GPIO_PULL_ENABLE);
	mt_set_gpio_pull_select(GPIO_OTG_IDDIG_EINT_PIN, GPIO_PULL_UP);

	mt_eint_set_sens(IDDIG_EINT_PIN, MT_LEVEL_SENSITIVE);
	mt_eint_set_hw_debounce(IDDIG_EINT_PIN,64);
	mt_eint_registration(IDDIG_EINT_PIN, EINTF_TRIGGER_LOW, mt_usb_ext_iddig_int, FALSE);
#else
	u32 phy_id_pull = 0;
	phy_id_pull = __raw_readl(U2PHYDTM1);
	phy_id_pull |= ID_PULL_UP;
	__raw_writel(phy_id_pull,U2PHYDTM1);

	musb_writel(mtk_musb->mregs,USB_L1INTM,IDDIG_INT_STATUS|musb_readl(mtk_musb->mregs,USB_L1INTM));
#endif
}
Пример #16
0
static int musb_platform_suspend(struct musb *musb)
{
	u32 l;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *pdata = dev->platform_data;
	struct omap_hwmod *oh = pdata->oh;

	if (!musb->clock)
		return 0;

	/* in any role */
	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l |= ENABLEFORCE;	/* enable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);

	pdata->enable_wakeup(oh->od);
	otg_set_suspend(musb->xceiv, 1);

	return 0;
}
Пример #17
0
static int musb_platform_resume(struct musb *musb)
{
	u32 l;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *pdata = dev->platform_data;
	struct omap_hwmod *oh = pdata->oh;

	if (!musb->clock)
		return 0;

	otg_set_suspend(musb->xceiv, 0);
	pm_runtime_enable(dev);
	pm_runtime_get_sync(dev);

	pdata->disable_wakeup(oh->od);
	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);

	return 0;
}
Пример #18
0
Файл: da8xx.c Проект: 7799/linux
static int da8xx_musb_init(struct musb *musb)
{
	void __iomem *reg_base = musb->ctrl_base;
	u32 rev;
	int ret = -ENODEV;

	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;

	/* Returns zero if e.g. not clocked */
	rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
	if (!rev)
		goto fail;

	usb_nop_xceiv_register();
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv)) {
		ret = -EPROBE_DEFER;
		goto fail;
	}

	setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);

	/* Reset the controller */
	musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);

	/* Start the on-chip PHY and its PLL. */
	phy_on();

	msleep(5);

	/* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */
	pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n",
		 rev, __raw_readl(CFGCHIP2),
		 musb_readb(reg_base, DA8XX_USB_CTRL_REG));

	musb->isr = da8xx_musb_interrupt;
	return 0;
fail:
	return ret;
}
Пример #19
0
static void otg_timer(unsigned long _musb)
{
	struct musb		*musb = (void *)_musb;
	void __iomem		*mregs = musb->mregs;
	u8			devctl;
	unsigned long		flags;

	devctl = musb_readb(mregs, MUSB_DEVCTL);
	dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
		otg_state_string(musb->xceiv->state));

	spin_lock_irqsave(&musb->lock, flags);
	switch (musb->xceiv->state) {
	case OTG_STATE_A_WAIT_VFALL:
		if (devctl & MUSB_DEVCTL_VBUS) {
			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
			break;
		}
		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
		musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
			MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
		break;
	case OTG_STATE_B_IDLE:
		if (!is_peripheral_enabled(musb))
			break;

		musb_writeb(mregs, MUSB_DEVCTL,
				devctl | MUSB_DEVCTL_SESSION);
		devctl = musb_readb(mregs, MUSB_DEVCTL);
		if (devctl & MUSB_DEVCTL_BDEVICE)
			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
		else
			musb->xceiv->state = OTG_STATE_A_IDLE;
		break;
	default:
		break;
	}
	spin_unlock_irqrestore(&musb->lock, flags);
}
Пример #20
0
void otg_int_init(void)
{
	//bool is_ready = mtk_musb->is_ready;
#ifdef ID_PIN_USE_EX_EINT
	mt_set_gpio_mode(ID_PIN_GPIO, GPIO_ID_PIN_EINT_PIN_M_EINT);
	mt_set_gpio_dir(ID_PIN_GPIO, GPIO_DIR_IN);
	mt_set_gpio_pull_enable(ID_PIN_GPIO, GPIO_PULL_ENABLE);
	mt_set_gpio_pull_select(ID_PIN_GPIO, GPIO_PULL_UP);
#else
	u32 phy_id_pull = 0;
	phy_id_pull = __raw_readl(U2PHYDTM1);
	phy_id_pull |= ID_PULL_UP;
	__raw_writel(phy_id_pull,U2PHYDTM1);
#endif
	//mt65xx_eint_set_sens(ID_PIN_EINT, MT65xx_LEVEL_SENSITIVE);
	//mt65xx_eint_set_hw_debounce(ID_PIN_EINT,64);
	//mtk_musb->is_ready = FALSE;
	//mt65xx_eint_registration(ID_PIN_EINT, FALSE, !DEVICE_INTTERRUPT, musb_id_pin_interrup,FALSE);
	//mtk_musb->is_ready = is_ready;

	musb_writel(mtk_musb->mregs,USB_L1INTM,IDDIG_INT_STATUS|musb_readl(mtk_musb->mregs,USB_L1INTM));
}
Пример #21
0
int musb_qmu_init(struct musb *musb)
{
	/* set DMA channel 0 burst mode to boost QMU speed */
	musb_writel(musb->mregs, 0x204, musb_readl(musb->mregs, 0x204) | 0x600);

#ifdef CONFIG_OF
	qmu_base = (void __iomem *)(mtk_musb->mregs + MUSB_QMUBASE);
	/* debug variable to check qmu_base issue */
	qmu_base_2 = (void __iomem *)(mtk_musb->mregs + MUSB_QMUBASE);
#else
	qmu_base = (void __iomem *)(USB_BASE + MUSB_QMUBASE);
	/* debug variable to check qmu_base issue */
	qmu_base_2 = (void __iomem *)(mtk_musb->mregs + MUSB_QMUBASE);
#endif
	mb();

	if (qmu_init_gpd_pool(musb->controller)) {
		QMU_ERR("[QMU]qmu_init_gpd_pool fail\n");
		return -1;
	}

	return 0;
}
Пример #22
0
 /* blocking notifier support */
int musb_notifier_call(struct notifier_block *nb,
		unsigned long event, void *unused)
{
	struct musb	*musb = container_of(nb, struct musb, nb);
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *pdata = dev->platform_data;
	struct omap_musb_board_data *data = pdata->board_data;
	static int hostmode;
	u32 val;

	switch (event) {
	case USB_EVENT_ID:
		DBG(1, "ID GND\n");

		/* configure musb into smartidle with wakeup enabled
		 * smart standby mode.
		 */

		musb_writel(musb->mregs, OTG_FORCESTDBY, 0);
		val = musb_readl(musb->mregs, OTG_SYSCONFIG);
		if (cpu_is_omap44xx())
			val |= SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP;
		else
			val |= SMARTIDLE | SMARTSTDBY | ENABLEWAKEUP;
		musb_writel(musb->mregs, OTG_SYSCONFIG, val);

		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			otg_init(musb->xceiv);
			hostmode = 1;
			musb_enable_vbus(musb);
		}

		val = __raw_readl(phymux_base +
				USBA0_OTG_CE_PAD1_USBA0_OTG_DP);

		val |= DP_WAKEUPENABLE;
		__raw_writel(val, phymux_base +
					USBA0_OTG_CE_PAD1_USBA0_OTG_DP);

		break;

	case USB_EVENT_VBUS:
		DBG(1, "VBUS Connect\n");

		/* configure musb into smartidle with wakeup enabled
		 * smart standby mode.
		 */
		musb_writel(musb->mregs, OTG_FORCESTDBY, 0);
		val = musb_readl(musb->mregs, OTG_SYSCONFIG);
		if (cpu_is_omap44xx())
			val |= SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP;
		else
			val |= SMARTIDLE | SMARTSTDBY | ENABLEWAKEUP;
		musb_writel(musb->mregs, OTG_SYSCONFIG, val);

		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			otg_init(musb->xceiv);
			if (!hostmode) {
				/* Enable VBUS Valid, AValid. Clear SESSEND.*/
				__raw_writel(IDDIG | AVALID | VBUSVALID,
					ctrl_base + USBOTGHS_CONTROL);
			}
		}

		break;

	case USB_EVENT_NONE:
		DBG(1, "VBUS Disconnect\n");

		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			/* enable this clock because in suspend interrupt
			 * handler phy clocks are disabled. If phy clocks are
			 * not enabled then DISCONNECT interrupt will not be
			 * reached to mentor
			 */
			otg_set_clk(musb->xceiv, 1);
			__raw_writel(SESSEND | IDDIG, ctrl_base +
							USBOTGHS_CONTROL);
			if (musb->xceiv->set_vbus)
				otg_set_vbus(musb->xceiv, 0);
			otg_shutdown(musb->xceiv);
		}
		hostmode = 0;
		/* configure in force idle/ standby */
		musb_writel(musb->mregs, OTG_FORCESTDBY, 1);
		val = musb_readl(musb->mregs, OTG_SYSCONFIG);
		val &= ~(SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP);
		val |= FORCEIDLE | FORCESTDBY;
		musb_writel(musb->mregs, OTG_SYSCONFIG, val);

		val = __raw_readl(phymux_base +
				USBA0_OTG_CE_PAD1_USBA0_OTG_DP);

		val &= ~DP_WAKEUPENABLE;
		__raw_writel(val, phymux_base +
					USBA0_OTG_CE_PAD1_USBA0_OTG_DP);
		break;
	default:
		DBG(1, "ID float\n");
		return NOTIFY_DONE;
	}

	return NOTIFY_OK;
}
Пример #23
0
int __init musb_platform_init(struct musb *musb)
{
	u32 l;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;
	int status;
	u32 val;

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	/* Fixme this can be enabled when load the gadget driver also*/
	musb_platform_resume(musb);

	/*powerup the phy as romcode would have put the phy in some state
	* which is impacting the core retention if the gadget driver is not
	* loaded.
	*/
	l = musb_readl(musb->mregs, OTG_INTERFSEL);

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	if (is_host_enabled(musb))
		musb->board_set_vbus = omap_set_vbus;

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
	plat->is_usb_active = is_musb_active;

	wake_lock_init(&plat->musb_lock, WAKE_LOCK_SUSPEND, "musb_wake_lock");
	if (cpu_is_omap44xx()) {
		phymux_base = ioremap(0x4A100000, SZ_1K);
		ctrl_base = ioremap(0x4A002000, SZ_1K);

		/* register for transciever notification*/
		status = otg_register_notifier(musb->xceiv, &musb->nb);

		if (status) {
			DBG(1, "notification register failed\n");
			wake_lock_destroy(&plat->musb_lock);
		}
		ctrl_base = ioremap(0x4A002000, SZ_1K);
		if (!ctrl_base) {
			dev_err(dev, "ioremap failed\n");
			return -ENOMEM;
		}
	}
	
	/* configure in force idle/ standby */
	musb_writel(musb->mregs, OTG_FORCESTDBY, 1);
	val = musb_readl(musb->mregs, OTG_SYSCONFIG);
	val &= ~(SMARTIDLEWKUP | NOSTDBY | ENABLEWAKEUP);
	val |= FORCEIDLE | FORCESTDBY;
	musb_writel(musb->mregs, OTG_SYSCONFIG,	val);


	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
	
	return 0;
}
void musb_platform_restore_context(struct musb *musb,
		struct musb_context_registers *musb_context)
{
	musb_writel(musb->mregs, OTG_SYSCONFIG, musb_context->otg_sysconfig);
	musb_writel(musb->mregs, OTG_FORCESTDBY, musb_context->otg_forcestandby);
}
int __init musb_platform_init(struct musb *musb, void *board_data)
{
	u32 l;
	struct omap_musb_board_data *data = board_data;

#if defined(CONFIG_ARCH_OMAP2430)
	omap_cfg_reg(AE5_2430_USB0HS_STP);
#endif

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	musb->xceiv = otg_get_transceiver();
	if (!musb->xceiv) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	musb_platform_resume(musb);

	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
	l &= ~ENABLEWAKEUP;	/* disable wakeup */
	l &= ~NOSTDBY;		/* remove possible nostdby */
	l |= SMARTSTDBY;	/* enable smart standby */
	l &= ~AUTOIDLE;		/* disable auto idle */
	l &= ~NOIDLE;		/* remove possible noidle */
	l |= SMARTIDLE;		/* enable smart idle */
	/*
	 * MUSB AUTOIDLE don't work in 3430.
	 * Workaround by Richard Woodruff/TI
	 */
	if (!cpu_is_omap3430())
		l |= AUTOIDLE;		/* enable auto idle */
	musb_writel(musb->mregs, OTG_SYSCONFIG, l);

	l = musb_readl(musb->mregs, OTG_INTERFSEL);

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	if (is_host_enabled(musb))
		musb->board_set_vbus = omap_set_vbus;

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);

	return 0;
}
Пример #26
0
static int omap2430_musb_init(struct musb *musb)
{
	u32 l;
	int status = 0;
	struct device *dev = musb->controller;
	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;

	/* We require some kind of external transceiver, hooked
	 * up through ULPI.  TWL4030-family PMICs include one,
	 * which needs a driver, drivers aren't always needed.
	 */
	if (dev->parent->of_node)
		musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
		    "usb-phy", 0);
	else
		musb->xceiv = devm_usb_get_phy_dev(dev, 0);

	if (IS_ERR(musb->xceiv)) {
		status = PTR_ERR(musb->xceiv);

		if (status == -ENXIO)
			return status;

		pr_err("HS USB OTG: no transceiver configured\n");
		return -EPROBE_DEFER;
	}

	musb->isr = omap2430_musb_interrupt;

	status = pm_runtime_get_sync(dev);
	if (status < 0) {
		dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
		goto err1;
	}

	l = musb_readl(musb->mregs, OTG_INTERFSEL);

	if (data->interface_type == MUSB_INTERFACE_UTMI) {
		/* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
		l &= ~ULPI_12PIN;       /* Disable ULPI */
		l |= UTMI_8BIT;         /* Enable UTMI  */
	} else {
		l |= ULPI_12PIN;
	}

	musb_writel(musb->mregs, OTG_INTERFSEL, l);

	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
			musb_readl(musb->mregs, OTG_REVISION),
			musb_readl(musb->mregs, OTG_SYSCONFIG),
			musb_readl(musb->mregs, OTG_SYSSTATUS),
			musb_readl(musb->mregs, OTG_INTERFSEL),
			musb_readl(musb->mregs, OTG_SIMENABLE));

	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);

	if (glue->status != OMAP_MUSB_UNKNOWN)
		omap_musb_set_mailbox(glue);

	usb_phy_init(musb->xceiv);

	pm_runtime_put_noidle(musb->controller);
	return 0;

err1:
	return status;
}
Пример #27
0
static int davinci_musb_init(struct musb *musb)
{
	void __iomem	*tibase = musb->ctrl_base;
	u32		revision;
	int 		ret = -ENODEV;

	usb_nop_xceiv_register();
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv)) {
		ret = -EPROBE_DEFER;
		goto unregister;
	}

	musb->mregs += DAVINCI_BASE_OFFSET;

	/* returns zero if e.g. not clocked */
	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
	if (revision == 0)
		goto fail;

	setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);

	davinci_musb_source_power(musb, 0, 1);

	/* dm355 EVM swaps D+/D- for signal integrity, and
	 * is clocked from the main 24 MHz crystal.
	 */
	if (machine_is_davinci_dm355_evm()) {
		u32	phy_ctrl = __raw_readl(USB_PHY_CTRL);

		phy_ctrl &= ~(3 << 9);
		phy_ctrl |= USBPHY_DATAPOL;
		__raw_writel(phy_ctrl, USB_PHY_CTRL);
	}

	/* On dm355, the default-A state machine needs DRVVBUS control.
	 * If we won't be a host, there's no need to turn it on.
	 */
	if (cpu_is_davinci_dm355()) {
		u32	deepsleep = __raw_readl(DM355_DEEPSLEEP);

		deepsleep &= ~DRVVBUS_FORCE;
		__raw_writel(deepsleep, DM355_DEEPSLEEP);
	}

	/* reset the controller */
	musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);

	/* start the on-chip PHY and its PLL */
	phy_on();

	msleep(5);

	/* NOTE:  irqs are in mixed mode, not bypass to pure-musb */
	pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
		revision, __raw_readl(USB_PHY_CTRL),
		musb_readb(tibase, DAVINCI_USB_CTRL_REG));

	musb->isr = davinci_musb_interrupt;
	return 0;

fail:
	usb_put_phy(musb->xceiv);
unregister:
	usb_nop_xceiv_unregister();
	return ret;
}
Пример #28
0
static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
{
	unsigned long	flags;
	irqreturn_t	retval = IRQ_NONE;
	struct musb	*musb = __hci;
	struct usb_otg	*otg = musb->xceiv->otg;
	void __iomem	*tibase = musb->ctrl_base;
	struct cppi	*cppi;
	u32		tmp;

	spin_lock_irqsave(&musb->lock, flags);

	/* NOTE: DaVinci shadows the Mentor IRQs.  Don't manage them through
	 * the Mentor registers (except for setup), use the TI ones and EOI.
	 *
	 * Docs describe irq "vector" registers associated with the CPPI and
	 * USB EOI registers.  These hold a bitmask corresponding to the
	 * current IRQ, not an irq handler address.  Would using those bits
	 * resolve some of the races observed in this dispatch code??
	 */

	/* CPPI interrupts share the same IRQ line, but have their own
	 * mask, state, "vector", and EOI registers.
	 */
	cppi = container_of(musb->dma_controller, struct cppi, controller);
	if (is_cppi_enabled() && musb->dma_controller && !cppi->irq)
		retval = cppi_interrupt(irq, __hci);

	/* ack and handle non-CPPI interrupts */
	tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG);
	musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp);
	dev_dbg(musb->controller, "IRQ %08x\n", tmp);

	musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK)
			>> DAVINCI_USB_RXINT_SHIFT;
	musb->int_tx = (tmp & DAVINCI_USB_TXINT_MASK)
			>> DAVINCI_USB_TXINT_SHIFT;
	musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK)
			>> DAVINCI_USB_USBINT_SHIFT;

	/* DRVVBUS irqs are the only proxy we have (a very poor one!) for
	 * DaVinci's missing ID change IRQ.  We need an ID change IRQ to
	 * switch appropriately between halves of the OTG state machine.
	 * Managing DEVCTL.SESSION per Mentor docs requires we know its
	 * value, but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
	 */
	if (tmp & (DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT)) {
		int	drvvbus = musb_readl(tibase, DAVINCI_USB_STAT_REG);
		void __iomem *mregs = musb->mregs;
		u8	devctl = musb_readb(mregs, MUSB_DEVCTL);
		int	err = musb->int_usb & MUSB_INTR_VBUSERROR;

		err = musb->int_usb & MUSB_INTR_VBUSERROR;
		if (err) {
			/* The Mentor core doesn't debounce VBUS as needed
			 * to cope with device connect current spikes. This
			 * means it's not uncommon for bus-powered devices
			 * to get VBUS errors during enumeration.
			 *
			 * This is a workaround, but newer RTL from Mentor
			 * seems to allow a better one: "re"starting sessions
			 * without waiting (on EVM, a **long** time) for VBUS
			 * to stop registering in devctl.
			 */
			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
			musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
			WARNING("VBUS error workaround (delay coming)\n");
		} else if (drvvbus) {
			MUSB_HST_MODE(musb);
			otg->default_a = 1;
			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
			del_timer(&otg_workaround);
		} else {
			musb->is_active = 0;
			MUSB_DEV_MODE(musb);
			otg->default_a = 0;
			musb->xceiv->state = OTG_STATE_B_IDLE;
			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
		}

		/* NOTE:  this must complete poweron within 100 msec
		 * (OTG_TIME_A_WAIT_VRISE) but we don't check for that.
		 */
		davinci_musb_source_power(musb, drvvbus, 0);
		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
				drvvbus ? "on" : "off",
				usb_otg_state_string(musb->xceiv->state),
				err ? " ERROR" : "",
				devctl);
		retval = IRQ_HANDLED;
	}

	if (musb->int_tx || musb->int_rx || musb->int_usb)
		retval |= musb_interrupt(musb);

	/* irq stays asserted until EOI is written */
	musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);

	/* poll for ID change */
	if (musb->xceiv->state == OTG_STATE_B_IDLE)
		mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);

	spin_unlock_irqrestore(&musb->lock, flags);

	return retval;
}
int musb_otg_exec_cmd(unsigned int cmd){

    unsigned char devctl;
    unsigned char intrusb;
    unsigned short intrtx;
    unsigned char power;
    unsigned short csr0;
    unsigned int usb_l1intp;
    unsigned int usb_l1ints;

    unsigned int ret;
    unsigned long timeout;
    bool timeout_flag = false;

    if(!mtk_musb){
        DBG(0,"mtk_musb is NULL,error!\n");
        }

	switch(cmd){
		case HOST_CMD_ENV_INIT:
    		musb_otg_env_init();
			return 0;
		case HOST_CMD_ENV_EXIT:
			musb_otg_env_exit ();
			return 0;
		}

    //init
    musb_writeb(mtk_musb->mregs, MUSB_POWER, 0x21);
    musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
    msleep(300);

    #ifdef DX_DBG
    devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
    power = musb_readb (mtk_musb->mregs,MUSB_POWER);
    intrusb = musb_readb(mtk_musb->mregs,MUSB_INTRUSB);
    DBG(0,"1:cmd=%d,devctl=0x%x,power=0x%x,intrusb=0x%x\n",cmd,devctl,power,intrusb);
    #endif
    musb_writew(mtk_musb->mregs,MUSB_INTRRX,0xffff);
    musb_writew(mtk_musb->mregs,MUSB_INTRTX,0xffff);
    musb_writeb(mtk_musb->mregs,MUSB_INTRUSB,0xff);
    msleep(10);
    #ifdef DX_DBG
    devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
    power = musb_readb (mtk_musb->mregs,MUSB_POWER);
    intrusb = musb_readb(mtk_musb->mregs,MUSB_INTRUSB);
    DBG(0,"2:cmd=%d,devctl=0x%x,power=0x%x,intrusb=0x%x\n",cmd,devctl,power,intrusb);
    #endif
    high_speed = false;
    g_exec = 1;

	DBG(0,"before exec:cmd=%d\n",cmd);

    switch(cmd){
        //electrical
        case OTG_CMD_E_ENABLE_VBUS:
        		DBG(0,"musb::enable VBUS!\n");
            musb_otg_set_session (true);
	    #ifdef MTK_FAN5405_SUPPORT
	    fan5405_set_opa_mode(1);
	    fan5405_set_otg_pl(1);
	    fan5405_set_otg_en(1);
            #elif defined(MTK_BQ24158_SUPPORT) 
            bq24158_set_opa_mode(1);
	    bq24158_set_otg_pl(1);
	    bq24158_set_otg_en(1);
	    #endif
            while(g_exec)
                msleep(100);
            musb_otg_set_session (false);
	    #ifdef MTK_FAN5405_SUPPORT
	    fan5405_config_interface_liao(0x01,0x30);
	    fan5405_config_interface_liao(0x02,0x8e);
            #elif defined(MTK_BQ24158_SUPPORT)
            bq24158_config_interface_reg(0x01,0x30);
	    bq24158_config_interface_reg(0x02,0x8e);
	    #endif
            break;
        case OTG_CMD_E_ENABLE_SRP: //need to clear session?
            DBG(0,"musb::enable srp!\n");
            musb_otg_reset_usb();
            USBPHY_WRITE8 (0x6c, 0x1);
            USBPHY_WRITE8 (0x6d, 0x1);
            musb_writeb(mtk_musb->mregs,0x7B,1);
            musb_otg_set_session (true);
            while(g_exec){
                msleep(100);
                }
            musb_otg_set_session (false);
            break;
        case OTG_CMD_E_START_DET_SRP:
            //need as a A-device
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
            devctl = musb_readb (mtk_musb->mregs, MUSB_DEVCTL);
             while(g_exec&&(devctl & 0x18)){//VBUS[1:0] should be 0, it indicate below SessionEnd
                DBG(0,"musb::not below session end!\n");
                msleep(100);
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            while(g_exec&&(!(devctl & 0x10))){
                DBG(0,"musb::not above session end!\n");
                msleep(100);
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            devctl |= MUSB_DEVCTL_SESSION;
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, devctl);
            while(g_exec)
                msleep(100);
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
            break;
        case OTG_CMD_E_START_DET_VBUS:
            usb_l1intp = musb_readl(mtk_musb->mregs,USB_L1INTP);
            usb_l1intp &= ~(1<<10);
            musb_writel(mtk_musb->mregs,USB_L1INTP,usb_l1intp);
            usb_l1ints = musb_readl(mtk_musb->mregs,USB_L1INTS);
            while((usb_l1ints&(1<<8))==0){
                DBG(0,"musb::vbus is 0!\n");
                msleep(100);
                usb_l1ints = musb_readl(mtk_musb->mregs,USB_L1INTS);
                }
            DBG(0,"musb::vbus is detected!\n");
            power = musb_readb (mtk_musb->mregs,MUSB_POWER);
            power |= MUSB_POWER_SOFTCONN;
            musb_writeb(mtk_musb->mregs, MUSB_POWER, power);
            while(g_exec)
                 msleep(100);
            musb_writeb(mtk_musb->mregs, MUSB_POWER, 0x21);
            break;

		case OTG_CMD_P_B_UUT_TD59:
			is_td_59 = true;
			if(is_td_59) DBG(0, "TD5.9 will be tested!\n");
			break;

        //protocal
        case OTG_CMD_P_A_UUT:
			DBG(0,"A-UUT starts...\n");
            //polling the session req from B-OPT and start a new session
            device_enumed = false;
TD_4_6:
            musb_otg_reset_usb();
			DBG(0,"A-UUT reset success\n");
            timeout = jiffies + 5*HZ;
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
            devctl = musb_readb (mtk_musb->mregs, MUSB_DEVCTL);
            while(g_exec&&(devctl & 0x18)){//VBUS[1:0] should be 0, it indicate below SessionEnd
                DBG(0,"musb::not below session end!\n");
                msleep(100);
                if(time_after(jiffies,timeout)){
                    timeout_flag = true;
                    break;
                    }
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            if(timeout_flag){
                timeout_flag = false;
                musb_otg_reset_usb();
                DBG(0,"timeout for below session end, after reset usb, devctl=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_DEVCTL));
                }
            DBG(0,"polling session request,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_SESSREQ);
            DBG(0,"polling session request,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            musb_otg_set_session(true);//session is set and VBUS will be out.
            #if 1
            power = musb_readb(mtk_musb->mregs,MUSB_POWER);
            power &= ~MUSB_POWER_SOFTCONN;
            musb_writeb(mtk_musb->mregs,MUSB_POWER,power);
            #endif
            //polling the connect interrupt from B-OPT
            DBG(0,"polling connect interrupt,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_CONNECT);
            DBG(0,"polling connect interrupt,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            if(DEV_NOT_CONNECT == ret){
                DBG(0,"device is not connected in 15s\n");
                g_otg_message.msg = OTG_MSG_DEV_NOT_RESPONSE;
                break;
                }
            DBG(0,"musb::connect interrupt is detected!\n");
            msleep(100);//the test is fail beacuse the reset starts less than100 ms from the B-OPT connect. the IF test needs
            //reset the bus,check whether it is a hs device
            musb_h_reset();//should last for more than 50ms, TD.4.2
            musb_h_enumerate();
            //suspend the bus
            csr0 = musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0);
            DBG(0,"after enum B-OPT,csr0=0x%x\n",csr0);
            musb_h_suspend();

            //polling the disconnect interrupt from B-OPT, and remote wakeup(TD.4.8)
            DBG(0,"polling disconnect or remote wakeup,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_DISCONNECT|MUSB_INTR_RESUME);
            DBG(0,"polling disconnect or remote wakeup,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            if(MUSB_INTR_RESUME == ret){
                //for TD4.8
                musb_h_remote_wakeup();
                //maybe need to access the B-OPT, get device descriptor
                if(g_exec)
                    wait_for_completion (&stop_event);
                break;
                }
            //polling the reset interrupt from B-OPT
            if(!(ret & MUSB_INTR_RESET)){
                DBG(0,"polling reset for B-OPT,begin\n");
                ret = musb_polling_bus_interrupt(MUSB_INTR_RESET);
                DBG(0,"polling reset for B-OPT,done,ret=0x%x\n",ret);
                if(TEST_IS_STOP == ret) break;
                if(DEV_NOT_RESET == ret){
                    if(g_exec)
                        wait_for_completion (&stop_event);
                    break;
                    }
                }

            DBG(0,"after receive reset,devctl=0x%x,csr0=0x%x\n",musb_readb(mtk_musb->mregs, MUSB_DEVCTL),musb_readw(mtk_musb->mregs, MUSB_OTG_CSR0));

            //enumerate and polling the suspend interrupt form B-OPT

            do{
                intrtx = musb_readw(mtk_musb->mregs, MUSB_INTRTX);
                mb();
                musb_writew(mtk_musb->mregs, MUSB_INTRTX, intrtx);
                intrusb = musb_readb(mtk_musb->mregs, MUSB_INTRUSB);
                mb();
                musb_writeb(mtk_musb->mregs, MUSB_INTRUSB,intrusb);
                if(intrtx || (intrusb&MUSB_INTR_SUSPEND)){
                    if(intrtx){
                        if(intrtx&0x1)
                            musb_d_enumerated();
                        }
                    if(intrusb){
                        if(intrusb&MUSB_INTR_SUSPEND){//maybe receive disconnect interrupt when the session is end
                            if(device_enumed){
                                break;//return form the while loop
                                }
                            else{//TD.4.6
                                musb_d_soft_connect (false);
                                goto TD_4_6;
                                }
                            }
                        }
                    }
                else
                    wait_for_completion_timeout(&stop_event,1);
                }
            while(g_exec);//the enum will be repeated for 5 times
            if(!g_exec){
                break;//return form the switch-case
                }
            DBG(0,"polling connect form B-OPT,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_CONNECT);//B-OPT will connect again 100ms after A disconnect
            DBG(0,"polling connect form B-OPT,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            musb_h_reset();//should reset bus again, TD.4.7
            wait_for_completion (&stop_event);
            DBG(0,"the test as A-UUT is done\n");
            break;

        case OTG_CMD_P_B_UUT:
            musb_otg_reset_usb();
            //The B-UUT issues an SRP to start a session with the A-OPT
            musb_otg_set_session (true);
            //100ms after VBUS begins to decay the A-OPT powers VBUS
            timeout = jiffies + 5 * HZ;
            devctl = musb_readb (mtk_musb->mregs, MUSB_DEVCTL);

            while(((devctl & MUSB_DEVCTL_VBUS)>>MUSB_DEVCTL_VBUS_SHIFT)<0x3){
                if(time_after(jiffies, timeout)){
                    timeout_flag = true;
                    break;
                    }
                msleep(100);
                devctl = musb_readb (mtk_musb->mregs,MUSB_DEVCTL);
                }
            if(timeout_flag){
				DBG(0,"B-UUT set vbus timeout\n");
                g_otg_message.msg = OTG_MSG_DEV_NOT_RESPONSE;
                timeout_flag = false;
                break;
                }

            //After detecting the VBUS, B-UUT should connect to the A_OPT
            power = musb_readb(mtk_musb->mregs, MUSB_POWER);
            power |= MUSB_POWER_HSENAB;
            musb_writeb(mtk_musb->mregs, MUSB_POWER,power);
//TD5_5:
            musb_d_soft_connect(true);

            device_enumed = false;
            //polling the reset single form the A-OPT
            DBG(0,"polling reset form A-OPT,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_RESET);
            DBG(0,"polling reset form A-OPT,done,ret=0x%x\n",ret);
            if(TEST_IS_STOP == ret) break;
            power = musb_readb(mtk_musb->mregs,MUSB_POWER);
            if(power & MUSB_POWER_HSMODE){
                high_speed = true;
            	}
            else
                high_speed = false;
            //The A-OPT enumerates the B-UUT
TD6_13:     do{
                intrtx = musb_readw(mtk_musb->mregs, MUSB_INTRTX);
                mb();
                musb_writew(mtk_musb->mregs, MUSB_INTRTX,intrtx);
                intrusb = musb_readb(mtk_musb->mregs, MUSB_INTRUSB);
                mb();
                musb_writeb(mtk_musb->mregs, MUSB_INTRUSB,intrusb);
                if(intrtx || (intrusb & 0xf7)){
                    if(intrtx){
                        //DBG(0,"B-enum,intrtx=0x%x\n",intrtx);
                        if(intrtx&0x1)
                            DBG(0,"ep0 interrupt\n");
                            musb_d_enumerated();
                        }
                    if(intrusb){
                        if(intrusb & 0xf7)
                            DBG(0,"B-enum,intrusb=0x%x,power=0x%x\n",intrusb,musb_readb(mtk_musb->mregs,MUSB_POWER));
                        if((device_enumed)&&(intrusb & MUSB_INTR_SUSPEND)){
                            DBG(0,"suspend interrupt is received,power=0x%x,devctl=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),musb_readb(mtk_musb->mregs,MUSB_DEVCTL));
                            break;
                            }
                        }
                    }
                else{
                    DBG(0,"power=0x%x,devctl=0x%x,intrtx=0x%x,intrusb=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),musb_readb(mtk_musb->mregs,MUSB_DEVCTL),musb_readw(mtk_musb->mregs,MUSB_INTRTX),musb_readb(mtk_musb->mregs,MUSB_INTRUSB));
                    wait_for_completion_timeout (&stop_event,1);
                    }
                }
            while(g_exec);
            if(!g_exec) break;
            DBG(0,"hnp start\n");
            if(intrusb & MUSB_INTR_RESUME)
                goto TD6_13;
            if(!(intrusb & MUSB_INTR_CONNECT)){
                //polling the connect from A-OPT, the UUT acts as host
                DBG(0,"polling connect or resume form A-OPT,begin\n");
                ret = musb_polling_bus_interrupt(MUSB_INTR_CONNECT|MUSB_INTR_RESUME);
                DBG(0,"polling connect or resume form A-OPT,done,ret=0x%x\n",ret);
                if(TEST_IS_STOP == ret) break;
                if(MUSB_INTR_RESUME == ret){
                    goto TD6_13;
                    }
                if(DEV_HNP_TIMEOUT == ret){
					DBG(0,"B-UUT HNP timeout\n");
                    devctl = musb_readb(mtk_musb->mregs,MUSB_DEVCTL);
                    //DBG(0,"hnp timeout,power=0x%x,devctl=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),devctl);
                    devctl &= ~MUSB_DEVCTL_HR;
                    musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,devctl);
					if(is_td_59)
						g_otg_message.msg = OTG_MSG_DEV_NOT_RESPONSE;
                    break;
                    }
                }
            //reset the bus and check whether it is a hs device
            musb_h_reset();
            musb_h_enumerate();
            //suspend the bus
            musb_h_suspend();
            //polling the disconnect interrupt from A-OPT
            DBG(0,"polling disconnect form A-OPT,begin\n");
            ret = musb_polling_bus_interrupt(MUSB_INTR_DISCONNECT);
            DBG(0,"polling disconnect form A-OPT,done,ret=0x%x\n",ret);
            //DBG(0,"power=0x%x,devctl=0x%x,intrusb=0x%x\n",musb_readb(mtk_musb->mregs,MUSB_POWER),musb_readb(mtk_musb->mregs,MUSB_DEVCTL),musb_readb(mtk_musb->mregs,MUSB_INTRUSB));
            if(TEST_IS_STOP == ret) break;
            DBG(0,"A-OPT is disconnected, UUT will be back to device\n");
            if(!(ret & MUSB_INTR_RESET)){
                musb_d_soft_connect(true);
                //polling the reset single form the A-OPT
                DBG(0,"polling reset form A-OPT,begin\n");
                ret = musb_polling_bus_interrupt(MUSB_INTR_RESET);
                //musb_d_reset ();
                DBG(0,"polling reset form A-OPT,done,ret=0x%x\n",ret);
                if(TEST_IS_STOP == ret) break;
                }
            device_enumed = false;
            if(g_exec)
                goto TD6_13;//TD5_5
            wait_for_completion(&stop_event);
            DBG(0,"test as B_UUT is done\n");
            break;

       	case HOST_CMD_TEST_SE0_NAK:
       	case HOST_CMD_TEST_J:
       	case HOST_CMD_TEST_K:
       	case HOST_CMD_TEST_PACKET:
       	case HOST_CMD_SUSPEND_RESUME:
       	case HOST_CMD_GET_DESCRIPTOR:
       	case HOST_CMD_SET_FEATURE:
       		musb_host_test_mode(cmd);
       		while(g_exec)
                msleep(100);
       		break;
        }
    DBG(0,"musb_otg_exec_cmd--\n");
    return 0;

}
int musb_otg_env_init(void){
    u8 power;
    //u8 intrusb;
    //step1: mask the PMU/PMIC EINT
    mtk_musb->usb_if = true;
    mtk_musb->is_host = true;//workaround for PMIC charger detection
    //mt65xx_eint_mask(EINT_CHR_DET_NUM);

    upmu_interrupt_chrdet_int_en(0);

    #ifndef MTK_FAN5405_SUPPORT
    #ifndef MTK_NCP1851_SUPPORT
    #ifndef MTK_BQ24196_SUPPORT
    #ifndef MTK_BQ24158_SUPPORT
    //set the drvvbus mode as drvvbus(mode 6)
#if !(defined(CONFIG_MT6585_FPGA) || defined(CONFIG_MT6577_FPGA) || defined(CONFIG_MT6589_FPGA) || defined(CONFIG_MT6582_FPGA))
#if defined(GPIO_OTG_DRVVBUS_PIN)
    mt_set_gpio_mode(GPIO_OTG_DRVVBUS_PIN,6);
    #endif
    #endif
    #endif
    #endif
    #endif
    #endif
    //step5: make sure to power on the USB module
    if(mtk_musb->power)
        mtk_musb->power = FALSE;
    musb_platform_enable(mtk_musb);
    //step6: clear session bit
    musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,0);
    //step7: disable and enable usb interrupt
    usb_l1intm_store = musb_readl(mtk_musb->mregs,USB_L1INTM);
    usb_intrrxe_store = musb_readw(mtk_musb->mregs,MUSB_INTRRXE);
    usb_intrtxe_store = musb_readw(mtk_musb->mregs,MUSB_INTRTXE);
    usb_intrusbe_store = musb_readb(mtk_musb->mregs,MUSB_INTRUSBE);

    musb_writel(mtk_musb->mregs,USB_L1INTM,0);
    musb_writew(mtk_musb->mregs,MUSB_INTRRXE,0);
    musb_writew(mtk_musb->mregs,MUSB_INTRTXE,0);
    musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0);
    musb_writew(mtk_musb->mregs,MUSB_INTRRX,0xffff);
    musb_writew(mtk_musb->mregs,MUSB_INTRTX,0xffff);
    musb_writeb(mtk_musb->mregs,MUSB_INTRUSB,0xff);
    free_irq (mtk_musb->nIrq, mtk_musb);
    musb_writel(mtk_musb->mregs,USB_L1INTM,0x105);
    musb_writew(mtk_musb->mregs,MUSB_INTRTXE,1);
    musb_writeb(mtk_musb->mregs,MUSB_INTRUSBE,0xf7);
    //setp8: set the index to 0 for ep0, maybe no need. Designers said it is better not to use the index register.
    musb_writeb(mtk_musb->mregs, MUSB_INDEX, 0);
    //setp9: init message
    g_otg_message.msg = 0;
    spin_lock_init(&g_otg_message.lock);

    init_completion(&stop_event);
    #ifdef DX_DBG
    power = musb_readb(mtk_musb->mregs,MUSB_POWER);
    DBG(0,"start the USB-IF test in EM,power=0x%x!\n",power);
    #endif

    return 0;
}