/** * dwc3_core_soft_reset_after_phy_init - Issues core soft reset * and PHY reset for HW versions which require core reset after * PHY initialization and reset * @dwc: pointer to our context structure */ static void dwc3_core_soft_reset_after_phy_init(struct dwc3 *dwc) { u32 reg; /* Reset PHYs */ usb_phy_reset(dwc->usb3_phy); usb_phy_reset(dwc->usb2_phy); msleep(100); /* Bring up PHYs */ usb_phy_init(dwc->usb2_phy); usb_phy_init(dwc->usb3_phy); msleep(100); /* Put Core in Reset */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT); msleep(100); /* Take Core out of reset state */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT); }
/** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure */ static int dwc3_core_reset(struct dwc3 *dwc) { int ret; /* Reset PHYs */ usb_phy_reset(dwc->usb2_phy); usb_phy_reset(dwc->usb3_phy); /* Initialize PHYs */ ret = dwc3_init_usb_phys(dwc); if (ret) { pr_err("%s: dwc3_init_phys returned %d\n", __func__, ret); return ret; } dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT); /* Perform core and PHY soft reset */ dwc3_core_and_phy_soft_reset(dwc); dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT); return 0; }
static void usb_do_work(struct work_struct *w) { struct usb_info *ui = container_of(w, struct usb_info, work); unsigned long iflags; unsigned flags, _vbus; for (;;) { spin_lock_irqsave(&ui->lock, iflags); flags = ui->flags; ui->flags = 0; _vbus = vbus; spin_unlock_irqrestore(&ui->lock, iflags); /* give up if we have nothing to do */ if (flags == 0) break; switch (ui->state) { case USB_STATE_IDLE: if (flags & USB_FLAG_START) { pr_info("msm72k_udc: IDLE -> ONLINE\n"); clk_set_rate(ui->ebi1clk, 128000000); udelay(10); if (ui->coreclk) clk_enable(ui->coreclk); clk_enable(ui->clk); clk_enable(ui->pclk); if (ui->otgclk) clk_enable(ui->otgclk); usb_reset(ui); ui->state = USB_STATE_ONLINE; usb_do_work_check_vbus(ui); } break; case USB_STATE_ONLINE: /* If at any point when we were online, we received * the signal to go offline, we must honor it */ if (flags & USB_FLAG_VBUS_OFFLINE) { pr_info("msm72k_udc: ONLINE -> OFFLINE\n"); /* synchronize with irq context */ spin_lock_irqsave(&ui->lock, iflags); ui->running = 0; ui->online = 0; msm72k_pullup(&ui->gadget, 0); spin_unlock_irqrestore(&ui->lock, iflags); if (ui->usb_connected) ui->usb_connected(0); /* terminate any transactions, etc */ flush_all_endpoints(ui); if (ui->driver) { printk(KERN_INFO "usb: notify offline\n"); ui->driver->disconnect(&ui->gadget); } usb_phy_reset(ui); /* power down phy, clock down usb */ spin_lock_irqsave(&ui->lock, iflags); usb_suspend_phy(ui); clk_disable(ui->pclk); clk_disable(ui->clk); if (ui->otgclk) clk_disable(ui->otgclk); if (ui->coreclk) clk_disable(ui->coreclk); clk_set_rate(ui->ebi1clk, 0); spin_unlock_irqrestore(&ui->lock, iflags); ui->state = USB_STATE_OFFLINE; usb_do_work_check_vbus(ui); break; } if (flags & USB_FLAG_RESET) { pr_info("msm72k_udc: ONLINE -> RESET\n"); usb_reset(ui); pr_info("msm72k_udc: RESET -> ONLINE\n"); break; } break; case USB_STATE_OFFLINE: /* If we were signaled to go online and vbus is still * present when we received the signal, go online. */ if ((flags & USB_FLAG_VBUS_ONLINE) && _vbus) { pr_info("msm72k_udc: OFFLINE -> ONLINE\n"); clk_set_rate(ui->ebi1clk, 128000000); udelay(10); if (ui->coreclk) clk_enable(ui->coreclk); clk_enable(ui->clk); clk_enable(ui->pclk); if (ui->otgclk) clk_enable(ui->otgclk); usb_reset(ui); /* detect shorted D+/D-, indicating AC power */ msleep(10); if ((readl(USB_PORTSC) & PORTSC_LS) == PORTSC_LS) if (ui->usb_connected) ui->usb_connected(2); ui->state = USB_STATE_ONLINE; usb_do_work_check_vbus(ui); } break; } } }
static void usb_reset(struct usb_info *ui) { unsigned long flags; printk(KERN_INFO "hsusb: reset controller\n"); spin_lock_irqsave(&ui->lock, flags); ui->running = 0; spin_unlock_irqrestore(&ui->lock, flags); /* To prevent phantom packets being received by the usb core on * some devices, put the controller into reset prior to * resetting the phy. */ writel(2, USB_USBCMD); msleep(10); #if 0 /* we should flush and shutdown cleanly if already running */ writel(0xffffffff, USB_ENDPTFLUSH); msleep(2); #endif if (usb_phy_reset(ui) < 0) pr_err("%s: Phy reset failed!\n", __func__); msleep(100); /* toggle non-driving mode after phy reset to ensure that * we cause a disconnect event to the host */ ulpi_write(ui, 0x18, 0x6); msleep(1); ulpi_write(ui, 0x8, 0x5); msleep(1); /* RESET */ writel(2, USB_USBCMD); msleep(10); #ifdef CONFIG_ARCH_MSM7X00A /* INCR4 BURST mode */ writel(0x01, USB_SBUSCFG); #else /* bursts of unspecified length. */ writel(0, USB_AHBBURST); /* Use the AHB transactor */ writel(0, USB_AHBMODE); #endif /* select DEVICE mode */ writel(0x12, USB_USBMODE); msleep(1); /* select ULPI phy */ writel(0x80000000, USB_PORTSC); ulpi_init(ui); writel(ui->dma, USB_ENDPOINTLISTADDR); configure_endpoints(ui); /* marking us offline will cause ept queue attempts to fail */ ui->online = 0; /* terminate any pending transactions */ flush_all_endpoints(ui); if (ui->driver) { printk(KERN_INFO "usb: notify offline\n"); ui->driver->disconnect(&ui->gadget); } /* enable interrupts */ writel(STS_URI | STS_SLI | STS_UI | STS_PCI, USB_USBINTR); /* go to RUN mode (D+ pullup enable) */ msm72k_pullup(&ui->gadget, 1); spin_lock_irqsave(&ui->lock, flags); ui->running = 1; spin_unlock_irqrestore(&ui->lock, flags); }
static int msm_hsusb_reset(struct msm_hcd *mhcd) { struct usb_hcd *hcd = mhcd_to_hcd(mhcd); struct msm_usb_host_platform_data *pdata; unsigned long timeout; int ret; if (mhcd->alt_core_clk) clk_prepare_enable(mhcd->alt_core_clk); ret = msm_ehci_phy_reset(mhcd); if (ret) { dev_err(mhcd->dev, "phy_reset failed\n"); return ret; } writel_relaxed(USBCMD_RESET, USB_USBCMD); timeout = jiffies + usecs_to_jiffies(LINK_RESET_TIMEOUT_USEC); while (readl_relaxed(USB_USBCMD) & USBCMD_RESET) { if (time_after(jiffies, timeout)) return -ETIMEDOUT; udelay(1); } /* select ULPI phy */ writel_relaxed(0x80000000, USB_PORTSC); pdata = mhcd->dev->platform_data; if (pdata && pdata->use_sec_phy) writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16), USB_PHY_CTRL2); /* Reset USB PHY after performing USB Link RESET */ if (hcd->phy) { usb_phy_reset(hcd->phy); usb_phy_init(hcd->phy); } else { msm_usb_phy_reset(mhcd); } msleep(100); writel_relaxed(0x0, USB_AHBBURST); writel_relaxed(0x08, USB_AHBMODE); /* Ensure that RESET operation is completed before turning off clock */ mb(); if (mhcd->alt_core_clk) clk_disable_unprepare(mhcd->alt_core_clk); /*rising edge interrupts with Dp rise and fall enabled*/ msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_RISE); msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_FALL); /*Clear the PHY interrupts by reading the PHY interrupt latch register*/ msm_ulpi_read(mhcd, ULPI_USB_INT_LATCH); return 0; }