static int msm_otg_set_suspend(struct otg_transceiver *xceiv, int suspend) { struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg); if (!dev || (dev != the_msm_otg)) return -ENODEV; if (suspend) msm_otg_suspend(dev); else { unsigned long timeout; disable_irq(dev->irq); msm_otg_resume(dev); if (!is_phy_clk_disabled()) goto out; timeout = jiffies + msecs_to_jiffies(500); enable_phy_clk(); while (is_phy_clk_disabled()) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to wakeup phy\n", __func__); otg_reset(dev); break; } msleep(1); } out: enable_irq(dev->irq); } return 0; }
static int msm_otg_suspend(struct msm_otg *dev) { unsigned long timeout; int vbus = 0; disable_irq(dev->irq); if (atomic_read(&dev->in_lpm)) goto out; ulpi_read(dev, 0x14);/* clear PHY interrupt latch register */ /* If there is no pmic notify support turn on phy comparators. */ if (!dev->pmic_notif_supp) ulpi_write(dev, 0x01, 0x30); ulpi_write(dev, 0x08, 0x09);/* turn off PLL on integrated phy */ timeout = jiffies + msecs_to_jiffies(500); disable_phy_clk(); while (!is_phy_clk_disabled()) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to suspend phy\n", __func__); /* Reset both phy and link */ otg_reset(dev, 1); goto out; } msleep(1); } writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); if (dev->hs_pclk) clk_disable(dev->hs_pclk); if (dev->hs_cclk) clk_disable(dev->hs_cclk); if (device_may_wakeup(dev->otg.dev)) { enable_irq_wake(dev->irq); if (dev->vbus_on_irq) enable_irq_wake(dev->vbus_on_irq); } atomic_set(&dev->in_lpm, 1); if (!vbus && dev->pmic_notif_supp) dev->pdata->pmic_enable_ldo(0); pr_info("%s: usb in low power mode\n", __func__); out: enable_irq(dev->irq); /* TBD: as there is no bus suspend implemented as of now * it should be dummy check */ return 0; }
static int msm_otg_suspend(struct msm_otg *dev) { unsigned long timeout; int vbus = 0; disable_irq(dev->irq); if (dev->in_lpm) goto out; otg_reset(dev); ulpi_read(dev, 0x14);/* clear PHY interrupt latch register */ ulpi_write(dev, 0x01, 0x30);/* PHY comparators on in LPM */ ulpi_write(dev, 0x08, 0x09);/* turn off PLL on integrated phy */ timeout = jiffies + msecs_to_jiffies(500); disable_phy_clk(); while (!is_phy_clk_disabled()) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to suspend phy\n", __func__); otg_reset(dev); goto out; } msleep(1); } writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); clk_disable(dev->clk); clk_disable(dev->pclk); if (device_may_wakeup(dev->otg.dev)) enable_irq_wake(dev->irq); dev->in_lpm = 1; /* TBD: as there is no bus suspend implemented as of now * it should be dummy check */ if (!vbus || release_wlocks) wake_unlock(&dev->wlock); pr_info("%s: usb in low power mode\n", __func__); out: enable_irq(dev->irq); return 0; }
static int msm_otg_set_suspend(struct otg_transceiver *xceiv, int suspend) { struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg); enum usb_otg_state state; unsigned long flags; if (!dev || (dev != the_msm_otg)) return -ENODEV; spin_lock_irqsave(&dev->lock, flags); state = dev->otg.state; spin_unlock_irqrestore(&dev->lock, flags); pr_debug("suspend request in state: %s\n", state_string(state)); if (suspend) { switch (state) { case OTG_STATE_A_HOST: clear_bit(A_BUS_REQ, &dev->inputs); wake_lock(&dev->wlock); queue_work(dev->wq, &dev->sm_work); break; case OTG_STATE_B_PERIPHERAL: if (xceiv->gadget->b_hnp_enable) { set_bit(A_BUS_SUSPEND, &dev->inputs); set_bit(B_BUS_REQ, &dev->inputs); wake_lock(&dev->wlock); queue_work(dev->wq, &dev->sm_work); } break; case OTG_STATE_A_PERIPHERAL: msm_otg_start_timer(dev, TA_BIDL_ADIS, A_BIDL_ADIS); break; default: break; } } else { unsigned long timeout; switch (state) { case OTG_STATE_A_PERIPHERAL: /* A-peripheral observed activity on bus. * clear A_BIDL_ADIS timer. */ msm_otg_del_timer(dev); break; case OTG_STATE_A_SUSPEND: /* Remote wakeup or resume */ set_bit(A_BUS_REQ, &dev->inputs); spin_lock_irqsave(&dev->lock, flags); dev->otg.state = OTG_STATE_A_HOST; spin_unlock_irqrestore(&dev->lock, flags); break; default: break; } if (suspend == atomic_read(&dev->in_lpm)) return 0; disable_irq(dev->irq); if (dev->pmic_notif_supp) dev->pdata->pmic_enable_ldo(1); msm_otg_resume(dev); if (!is_phy_clk_disabled()) goto out; timeout = jiffies + usecs_to_jiffies(100); enable_phy_clk(); while (is_phy_clk_disabled()) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to wakeup phy\n", __func__); /* Reset both phy and link */ otg_reset(dev, 1); break; } udelay(10); } out: enable_irq(dev->irq); } return 0; }
static int msm_otg_suspend(struct msm_otg *dev) { unsigned long timeout; int vbus = 0; unsigned otgsc; disable_irq(dev->irq); if (dev->in_lpm) goto out; /* Don't reset if mini-A cable is connected */ if (!is_host()) otg_reset(dev); /* In case of fast plug-in and plug-out inside the otg_reset() the * servicing of BSV is missed (in the window of after phy and link * reset). Handle it if any missing bsv is detected */ if (is_b_sess_vld() && !is_host()) { otgsc = readl(USB_OTGSC); writel(otgsc, USB_OTGSC); pr_info("%s:Process mising BSV\n", __func__); msm_otg_start_peripheral(&dev->otg, 1); enable_irq(dev->irq); return -1; } ulpi_read(dev, 0x14);/* clear PHY interrupt latch register */ /* If there is no pmic notify support turn on phy comparators. */ if (!dev->pmic_notif_supp) ulpi_write(dev, 0x01, 0x30); ulpi_write(dev, 0x08, 0x09);/* turn off PLL on integrated phy */ timeout = jiffies + msecs_to_jiffies(500); disable_phy_clk(); while (!is_phy_clk_disabled()) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to suspend phy\n", __func__); otg_reset(dev); goto out; } msleep(1); } writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); clk_disable(dev->pclk); if (dev->cclk) clk_disable(dev->cclk); if (device_may_wakeup(dev->otg.dev)) { enable_irq_wake(dev->irq); if (dev->vbus_on_irq) enable_irq_wake(dev->vbus_on_irq); } dev->in_lpm = 1; if (!vbus && dev->pmic_notif_supp) dev->pmic_enable_ldo(0); pr_info("%s: usb in low power mode\n", __func__); out: enable_irq(dev->irq); /* TBD: as there is no bus suspend implemented as of now * it should be dummy check */ return 0; }