static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) { struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); struct usb_hcd *hcd = priv->hcd; if (pdata && pdata->exit) pdata->exit(pdev); if (pdata->otg) otg_shutdown(pdata->otg); usb_remove_hcd(hcd); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); clk_disable(priv->usbclk); clk_put(priv->usbclk); if (priv->ahbclk) { clk_disable(priv->ahbclk); clk_put(priv->ahbclk); } if (priv->phy1clk) { clk_disable(priv->phy1clk); clk_put(priv->phy1clk); } kfree(priv); return 0; }
static void omap2430_musb_disable(struct musb *musb) { #if 0 if (musb->xceiv->last_event) otg_shutdown(musb->xceiv); #endif }
/* blocking notifier support */ static int musb_otg_notifications(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; switch (event) { case USB_EVENT_ID: dev_dbg(musb->controller, "ID GND\n"); if (is_otg_enabled(musb)) { if (musb->gadget_driver) { pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } } else { pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } break; case USB_EVENT_VBUS: dev_dbg(musb->controller, "VBUS Connect\n"); if (musb->gadget_driver) pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); break; case USB_EVENT_NONE: dev_dbg(musb->controller, "VBUS Disconnect\n"); if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) if (musb->gadget_driver) { pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); } if (data->interface_type == MUSB_INTERFACE_UTMI) { if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); break; default: dev_dbg(musb->controller, "ID float\n"); return NOTIFY_DONE; } return NOTIFY_OK; }
/* blocking notifier support */ static int musb_otg_notifications(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; switch (event) { case USB_EVENT_ID: DBG(4, "ID GND\n"); if (is_otg_enabled(musb)) { #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { otg_init(musb->xceiv); if (data->interface_type == MUSB_INTERFACE_UTMI) omap2430_musb_set_vbus(musb, 1); } #endif } else { otg_init(musb->xceiv); if (data->interface_type == MUSB_INTERFACE_UTMI) omap2430_musb_set_vbus(musb, 1); } break; case USB_EVENT_VBUS: DBG(4, "VBUS Connect\n"); otg_init(musb->xceiv); break; case USB_EVENT_NONE: DBG(4, "VBUS Disconnect\n"); if (data->interface_type == MUSB_INTERFACE_UTMI) { if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); break; default: DBG(4, "ID float\n"); return NOTIFY_DONE; } return NOTIFY_OK; }
void musb_platform_try_idle(struct musb *musb, unsigned long timeout) { unsigned long default_timeout = jiffies + msecs_to_jiffies(3); static unsigned long last_timer; u32 val; if (timeout == 0) timeout = default_timeout; /* Never idle if active, or when VBUS timeout is not set as host */ if (musb->is_active || ((musb->a_wait_bcon == 0) && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); del_timer(&musb_idle_timer); last_timer = jiffies; return; } if (musb->xceiv->state == OTG_STATE_UNDEFINED) { /* disable the phy clock when the gadget driver is unloaded. * Powerdown the phy and configure the musb sysconfig to * force standby/idle. * this will allow the core to hit retention and offmode */ otg_shutdown(musb->xceiv); /* configure in force idle/ standby */ val = musb_readl(musb->mregs, OTG_SYSCONFIG); val &= ~(SMARTIDLEWKUP | SMARTSTDBY | NOSTDBY | ENABLEWAKEUP); val |= FORCEIDLE | FORCESTDBY; musb_writel(musb->mregs, OTG_SYSCONFIG, val); musb_writel(musb->mregs, OTG_FORCESTDBY, 1); } if (time_after(last_timer, timeout)) { if (!timer_pending(&musb_idle_timer)) last_timer = timeout; else { DBG(4, "Longer idle timer already pending, ignoring\n"); return; } } last_timer = timeout; DBG(4, "%s inactive, for idle timer for %lu ms\n", otg_state_string(musb), (unsigned long)jiffies_to_msecs(timeout - jiffies)); mod_timer(&musb_idle_timer, timeout); }
static void musb_otg_notifier_work(struct work_struct *data_notifier_work) { struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work); struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; switch (musb->xceiv_event) { case USB_EVENT_ID: dev_dbg(musb->controller, "ID GND\n"); if (!is_otg_enabled(musb) || musb->gadget_driver) { pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } break; case USB_EVENT_VBUS: dev_dbg(musb->controller, "VBUS Connect\n"); if (musb->gadget_driver) pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); break; case USB_EVENT_NONE: dev_dbg(musb->controller, "VBUS Disconnect\n"); if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) if (musb->gadget_driver) { pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); } if (data->interface_type == MUSB_INTERFACE_UTMI) { if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); break; default: dev_dbg(musb->controller, "ID float\n"); } }
/* 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; }
static void musb_otg_notifier_work(struct work_struct *data_notifier_work) { struct musb_otg_work *otg_work = container_of(data_notifier_work, struct musb_otg_work, work); struct musb *musb = otg_work->musb; struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; enum usb_xceiv_events xceiv_event = otg_work->xceiv_event; kfree(otg_work); switch (xceiv_event) { case USB_EVENT_ID: dev_dbg(musb->controller, "ID GND\n"); if (is_otg_enabled(musb)) { #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } #endif } else { pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } break; case USB_EVENT_CHARGER: dev_dbg(musb->controller, "Dedicated charger connect\n"); musb->is_ac_charger = true; break; case USB_EVENT_VBUS: dev_dbg(musb->controller, "VBUS Connect\n"); #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) pm_runtime_get_sync(musb->controller); #endif otg_init(musb->xceiv); break; case USB_EVENT_NONE: if (musb->is_ac_charger) { dev_dbg(musb->controller, "Dedicated charger disconnect\n"); musb->is_ac_charger = false; break; } dev_dbg(musb->controller, "VBUS Disconnect\n"); #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) if (musb->gadget_driver) #endif { pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); } if (data->interface_type == MUSB_INTERFACE_UTMI) { omap2430_musb_set_vbus(musb, 0); if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); break; default: dev_dbg(musb->controller, "ID float\n"); return; } return; }
static void musb_otg_notifier_work(struct work_struct *data_notifier_work) { struct musb_otg_work *otg_work = container_of(data_notifier_work, struct musb_otg_work, work); struct musb *musb = otg_work->musb; struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; enum usb_xceiv_events xceiv_event = otg_work->xceiv_event; unsigned long flags; #ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM int ret = 0; #endif kfree(otg_work); switch (xceiv_event) { case USB_EVENT_ID: dev_info(musb->controller, "ID GND\n"); musb->xceiv->state = OTG_STATE_A_IDLE; #ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM ret = omap2430_async_resume(musb); if (ret < 0) return; #endif if (is_otg_enabled(musb)) { #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { musb_otg_init(musb); } #endif } else { musb_otg_init(musb); } #ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM musb_add_hcd(musb); #endif break; case USB_EVENT_VBUS_CHARGER: dev_info(musb->controller, "USB/TA Connect\n"); /* This event received from ta_connect_irq * when a usb cable is connected. Logic has still * not identified whether this is a usb cable or TA. * So just break here. */ break; case USB_EVENT_VBUS: dev_info(musb->controller, "VBUS Connect\n"); #ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM ret = omap2430_async_resume(musb); if (ret < 0) return; #endif #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) pm_runtime_get_sync(musb->controller); #endif otg_init(musb->xceiv); #ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM musb_start(musb); musb_platform_pullup(musb, 1); #endif break; case USB_EVENT_CHARGER: dev_info(musb->controller, "Dedicated charger connect\n"); musb->is_ac_charger = true; break; case USB_EVENT_HOST_NONE: #ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM dev_info(musb->controller, "USB host Disconnect. ID float\n"); if (!omap2430_async_resumed(musb)) { dev_err(musb->controller, "async suspended. abnormal state.\n"); return; } musb_stop(musb); musb_remove_hcd(musb); if (data->interface_type == MUSB_INTERFACE_UTMI) { omap2430_musb_set_vbus(musb, 0); if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); musb_otg_core_reset(musb); ret = omap2430_async_suspend(musb); if (ret < 0) return; break; #endif case USB_EVENT_NONE: if (musb->is_ac_charger) { dev_info(musb->controller, "Dedicated charger disconnect\n"); musb->is_ac_charger = false; break; } dev_info(musb->controller, "VBUS Disconnect\n"); #ifndef CONFIG_USB_SAMSUNG_OMAP_NORPM if (pm_runtime_suspended(musb->controller)) { dev_err(musb->controller, "runtime pm suspended. abnormal state.\n"); return; } spin_lock_irqsave(&musb->lock, flags); musb_g_disconnect(musb); spin_unlock_irqrestore(&musb->lock, flags); #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) if (musb->gadget_driver) #endif { pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); } if (data->interface_type == MUSB_INTERFACE_UTMI) { omap2430_musb_set_vbus(musb, 0); if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); #else if (!omap2430_async_resumed(musb)) { dev_err(musb->controller, "async suspended. abnormal state.\n"); return; } musb_platform_pullup(musb, 0); spin_lock_irqsave(&musb->lock, flags); musb_stop(musb); musb_g_disconnect(musb); musb_all_ep_flush(musb); spin_unlock_irqrestore(&musb->lock, flags); if (data->interface_type == MUSB_INTERFACE_UTMI) omap2430_musb_set_vbus(musb, 0); otg_shutdown(musb->xceiv); musb_otg_core_reset(musb); ret = omap2430_async_suspend(musb); if (ret < 0) return; #endif break; default: dev_info(musb->controller, "ID float\n"); } }
static void musb_otg_notifier_work(struct work_struct *data_notifier_work) { u32 val; struct musb_otg_work *otg_work = container_of(data_notifier_work, struct musb_otg_work, work); struct musb *musb = otg_work->musb; struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; enum usb_xceiv_events xceiv_event = otg_work->xceiv_event; static int last_event = -1; kfree(otg_work); /* avoid duplicate notifications */ if (last_event == xceiv_event) { WARN(1, "Duplicated event(%d): ignored\n", xceiv_event); return; } /* check for incorrect transitions */ if ((last_event == USB_EVENT_VBUS && xceiv_event == USB_EVENT_ID) || (last_event == USB_EVENT_ID && xceiv_event == USB_EVENT_VBUS)) { WARN(1, "Incorrect transition (%d)->(%d)\n", last_event, xceiv_event); } /* store last event */ last_event = xceiv_event; switch (xceiv_event) { case USB_EVENT_ID: dev_dbg(musb->controller, "ID GND\n"); if (is_otg_enabled(musb)) { #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { pm_runtime_get_sync(musb->controller); val = musb_readl(musb->mregs, OTG_INTERFSEL); otg_set_suspend(musb->xceiv, 1); if (data->interface_type == MUSB_INTERFACE_UTMI) { val &= ~ULPI_12PIN; val |= UTMI_8BIT; } else { val |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, val); otg_set_suspend(musb->xceiv, 0); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } #endif } else { pm_runtime_get_sync(musb->controller); val = musb_readl(musb->mregs, OTG_INTERFSEL); otg_set_suspend(musb->xceiv, 1); if (data->interface_type == MUSB_INTERFACE_UTMI) { val &= ~ULPI_12PIN; val |= UTMI_8BIT; } else { val |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, val); otg_set_suspend(musb->xceiv, 0); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } break; case USB_EVENT_CHARGER: dev_dbg(musb->controller, "Dedicated charger connect\n"); musb->is_ac_charger = true; break; case USB_EVENT_VBUS: dev_dbg(musb->controller, "VBUS Connect\n"); #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { pm_runtime_get_sync(musb->controller); val = musb_readl(musb->mregs, OTG_INTERFSEL); otg_set_suspend(musb->xceiv, 1); if (data->interface_type == MUSB_INTERFACE_UTMI) { val &= ~ULPI_12PIN; val |= UTMI_8BIT; } else { val |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, val); otg_set_suspend(musb->xceiv, 0); } #endif otg_init(musb->xceiv); break; case USB_EVENT_NONE: if (musb->is_ac_charger) { dev_dbg(musb->controller, "Dedicated charger disconnect\n"); musb->is_ac_charger = false; break; } dev_dbg(musb->controller, "VBUS Disconnect\n"); pm_runtime_get_sync(musb->controller); if (data->interface_type == MUSB_INTERFACE_UTMI) { omap2430_musb_set_vbus(musb, 0); if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); otg_set_suspend(musb->xceiv, 1); val = musb_readl(musb->mregs, OTG_INTERFSEL); val |= ULPI_12PIN; musb_writel(musb->mregs, OTG_INTERFSEL, val); pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) if (musb->gadget_driver) #endif pm_runtime_put_autosuspend(musb->controller); break; default: dev_dbg(musb->controller, "ID float\n"); } }
/* blocking notifier support */ void cpcap_musb_notifier_call(unsigned long event) { struct musb *musb = g_musb; 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; u8 power; switch (event) { case USB_EVENT_ID: DBG(1, "ID GND\n"); /* configure musb into smartidle with wakeup enabled * smart standby mode. */ omap_pm_set_max_mpu_wakeup_lat(&pdata->musb_qos_request, 4000); 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) { phy_init(); otg_init(musb->xceiv); /* enable VBUS valid, id groung*/ __raw_writel(AVALID | VBUSVALID, ctrl_base + USBOTGHS_CONTROL); 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); } hostmode = 1; musb_start(musb); musb_set_vbus(musb, 1); 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); power = musb_readb(musb->mregs, MUSB_POWER); power &= ~MUSB_POWER_SOFTCONN; musb_writeb(musb->mregs, MUSB_POWER, power); if (data->interface_type == MUSB_INTERFACE_UTMI) { phy_init(); 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); phy_shutdown(); } /* 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); omap_pm_set_max_mpu_wakeup_lat(&pdata->musb_qos_request, -1); if (data->interface_type == MUSB_INTERFACE_UTMI) { 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); } if (hostmode) { musb_stop(musb); musb_set_vbus(musb, 0); } hostmode = 0; break; default: DBG(1, "ID float\n"); } }
static void musb_otg_notifier_work(struct work_struct *data_notifier_work) { u32 val; struct musb_otg_work *otg_work = container_of(data_notifier_work, struct musb_otg_work, work); struct musb *musb = otg_work->musb; struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; enum usb_xceiv_events xceiv_event = otg_work->xceiv_event; int status; kfree(otg_work); if (xceiv_event == xceiv_event_last) { /* sync pm runtime if already got */ if (xceiv_event == USB_EVENT_VBUS || xceiv_event == USB_EVENT_ID) { pm_runtime_put_sync(musb->controller); } } xceiv_event_last = xceiv_event; switch (xceiv_event) { case USB_EVENT_ID: dev_dbg(musb->controller, "ID GND\n"); pm_runtime_get_sync(musb->controller); if (is_otg_enabled(musb)) { #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { val = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { val &= ~ULPI_12PIN; val |= UTMI_8BIT; } else { val |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, val); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } #endif } else { val = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { val &= ~ULPI_12PIN; val |= UTMI_8BIT; } else { val |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, val); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } break; case USB_EVENT_CHARGER: dev_dbg(musb->controller, "Dedicated charger connect\n"); musb->is_ac_charger = true; break; case USB_EVENT_VBUS: dev_dbg(musb->controller, "VBUS Connect\n"); pm_runtime_get_sync(musb->controller); #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { val = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { val &= ~ULPI_12PIN; val |= UTMI_8BIT; } else { val |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, val); } #endif otg_init(musb->xceiv); break; case USB_EVENT_NONE: if (musb->is_ac_charger) { dev_dbg(musb->controller, "Dedicated charger disconnect\n"); musb->is_ac_charger = false; break; } dev_dbg(musb->controller, "VBUS Disconnect\n"); // pm_runtime_get_sync(musb->controller); if (data->interface_type == MUSB_INTERFACE_UTMI) { omap2430_musb_set_vbus(musb, 0); if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } otg_shutdown(musb->xceiv); val = musb_readl(musb->mregs, OTG_INTERFSEL); val |= ULPI_12PIN; musb_writel(musb->mregs, OTG_INTERFSEL, val); #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) { if (musb->gadget_driver) #endif { pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); } #ifdef CONFIG_USB_GADGET_MUSB_HDRC else { pm_runtime_put_sync(musb->controller); } } else { pm_runtime_put_sync(musb->controller); } #endif break; default: dev_dbg(musb->controller, "ID float\n"); } }