void dwc3_set_mode(struct dwc3 *dwc, u32 mode) { u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); /* * Set this bit so that device attempts three more times at SS, even * if it failed previously to operate in SS mode. */ reg |= DWC3_GCTL_U2RSTECN; if (mode == DWC3_GCTL_PRTCAP_HOST) { /* * Allow ITP generated off of ref clk based counter instead * of UTMI/ULPI clk based counter, when superspeed only is * active so that UTMI/ULPI PHY can be suspened. */ reg |= DWC3_GCTL_SOFITPSYNC; reg &= ~(DWC3_GCTL_PWRDNSCALEMASK); reg |= DWC3_GCTL_PWRDNSCALE(2); } else if (mode == DWC3_GCTL_PRTCAP_DEVICE) { reg &= ~(DWC3_GCTL_PWRDNSCALEMASK); reg |= DWC3_GCTL_PWRDNSCALE(2); reg &= ~(DWC3_GCTL_SOFITPSYNC); } reg |= DWC3_GCTL_U2EXIT_LFPS; dwc3_writel(dwc->regs, DWC3_GCTL, reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); }
void dwc3_set_mode(struct dwc3 *dwc, u32 mode) { u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); reg |= DWC3_GCTL_U2RSTECN; reg &= ~(DWC3_GCTL_SOFITPSYNC); reg &= ~(DWC3_GCTL_PWRDNSCALEMASK); reg |= DWC3_GCTL_PWRDNSCALE(2); reg |= DWC3_GCTL_U2EXIT_LFPS; dwc3_writel(dwc->regs, DWC3_GCTL, reg); if (mode == DWC3_GCTL_PRTCAP_OTG || mode == DWC3_GCTL_PRTCAP_HOST) { if (dwc->revision < DWC3_REVISION_250A) { reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg |= DWC3_GCTL_SOFITPSYNC; dwc3_writel(dwc->regs, DWC3_GCTL, reg); } else { reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); reg |= DWC3_GFLADJ_REFCLK_LPM_SEL; dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); } } reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); }
static void dwc3_otg_set_hsphy_auto_suspend(struct dwc3_otg *dotg, bool susp) { struct dwc3 *dwc = dotg->dwc; u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); if (susp) reg |= DWC3_GUSB2PHYCFG_SUSPHY; else reg &= ~(DWC3_GUSB2PHYCFG_SUSPHY); dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); }
/** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure */ static int dwc3_core_soft_reset(struct dwc3 *dwc) { u32 reg; int ret; /* Before Resetting PHY, put Core in Reset */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); /* Assert USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); /* Assert USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); usb_phy_init(dwc->usb2_phy); usb_phy_init(dwc->usb3_phy); ret = phy_init(dwc->usb2_generic_phy); if (ret < 0) return ret; ret = phy_init(dwc->usb3_generic_phy); if (ret < 0) { phy_exit(dwc->usb2_generic_phy); return ret; } mdelay(100); /* Clear USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); /* Clear USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(100); /* After PHYs are stable we can take Core out of reset state */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); return 0; }
/** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure */ static void dwc3_core_soft_reset(struct dwc3 *dwc) { u32 reg; if (dwc->core_reset_after_phy_init) return dwc3_core_soft_reset_after_phy_init(dwc); /* Before Resetting PHY, put Core in Reset */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); /* Bring up PHYs */ usb_phy_init(dwc->usb2_phy); usb_phy_init(dwc->usb3_phy); dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT); /* Assert USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); /* Assert USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(100); /* Clear USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); /* Clear USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(100); /* After PHYs are stable we can 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); }
/** * Peforms core soft reset and PHY soft reset of HS and SS PHYs. * If used as a part of POR or init sequence it is recommended * that we should perform hard reset and init of the PHYs prior * to invoking this function. * @dwc: pointer to our context structure */ static void dwc3_core_and_phy_soft_reset(struct dwc3 *dwc) { u32 reg; /* Before Resetting PHY, put Core in Reset */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); /* Assert USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); usleep_range(1000, 1200); /* Clear USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_DELAYP1TRANS; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); /* Assert USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); usleep_range(1000, 1200); /* Clear USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); usleep_range(200, 500); /* After PHYs are stable we can take Core out of reset state */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); usleep_range(1000, 1200); }
static void dwc3_core_soft_reset(struct dwc3 *dwc) { u32 reg; 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); reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(10); reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(10); 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 void dwc3_core_soft_reset(struct dwc3 *dwc) { u32 reg; /* Before Resetting PHY, put Core in Reset */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); /* Assert USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); /* Assert USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); //usb_phy_init(dwc->usb3_phy); dwc_usb3_phy_init(); mdelay(100); /* Clear USB3 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); /* Clear USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(100); /* After PHYs are stable we can take Core out of reset state */ reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; dwc3_writel(dwc->regs, DWC3_GCTL, reg); }
void setup_dwc3(void) { u32 reg; u32 revision; revision = read32(USB_HOST3_PHY_BASE + DWC3_GSNPSID); /* This should read as U3 followed by revision number */ if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) printk(BIOS_INFO, "Error in reading Version\n"); printk(BIOS_INFO, "Version = %x\n", revision); /* issue device SoftReset too */ write32(USB_HOST3_PHY_BASE + DWC3_DCTL, DWC3_DCTL_CSFTRST); do { reg = read32(USB_HOST3_PHY_BASE + DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) break; udelay(10); } while (true); printk(BIOS_INFO, "software reset done\n"); /* Before Resetting PHY, put Core in Reset */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); /* Assert USB3 PHY reset */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg); /* Assert USB2 PHY reset */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg); qcom_baldur_hs_phy_init(); qcom_uni_ss_phy_init(); mdelay(100); /* Clear USB3 PHY reset */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg); /* Clear USB2 PHY reset */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg); mdelay(100); /* After PHYs are stable we can take Core out of reset state */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); #if 0 /* Enable Suspend USB2.0 HS/FS/LS PHY (SusPHY) */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_SUSPHY; write32(USB_HOST3_PHY_BASE + DWC3_GUSB2PHYCFG(0), reg); /* Enable Suspend USB3.0 SS PHY (Suspend_en) */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_SUSPHY; write32(USB_HOST3_PHY_BASE + DWC3_GUSB3PIPECTL(0), reg); #endif /* configure controller in Host mode */ reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(0x1); /* host mode */ write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); printk(BIOS_INFO, "USB Host mode reg = %x\n", reg); reg = read32(USB_HOST3_PHY_BASE + DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; reg &= ~DWC3_GCTL_DISSCRAMBLE; reg &= ~DWC3_GCTL_DSBLCLKGTNG; /* * WORKAROUND: DWC3 revisions <1.90a have a bug * where the device can fail to connect at SuperSpeed * and falls back to high-speed mode which causes * the device to enter a Connect/Disconnect loop */ if (revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; write32(USB_HOST3_PHY_BASE + DWC3_GCTL, reg); }
/** * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success. The USB PHY interfaces are configured but not * initialized. The PHY interfaces and the PHYs get initialized together with * the core in dwc3_core_init. */ static int dwc3_phy_setup(struct dwc3 *dwc) { u32 reg; int ret; reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); /* * Make sure UX_EXIT_PX is cleared as that causes issues with some * PHYs. Also, this bit is not supposed to be used in normal operation. */ reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; /* * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY * to '0' during coreConsultant configuration. So default value * will be '0' when the core is reset. Application needs to set it * to '1' after the core initialization is completed. */ if (dwc->revision > DWC3_REVISION_194A) reg |= DWC3_GUSB3PIPECTL_SUSPHY; if (dwc->u2ss_inp3_quirk) reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; if (dwc->dis_rxdet_inp3_quirk) reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; if (dwc->req_p1p2p3_quirk) reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; if (dwc->del_p1p2p3_quirk) reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; if (dwc->del_phy_power_chg_quirk) reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; if (dwc->lfps_filter_quirk) reg |= DWC3_GUSB3PIPECTL_LFPSFILT; if (dwc->rx_detect_poll_quirk) reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; if (dwc->tx_de_emphasis_quirk) reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); if (dwc->dis_u3_susphy_quirk) reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; if (dwc->dis_del_phy_power_chg_quirk) reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); /* Select the HS PHY interface */ switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: if (dwc->hsphy_interface && !strncmp(dwc->hsphy_interface, "utmi", 4)) { reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; break; } else if (dwc->hsphy_interface && !strncmp(dwc->hsphy_interface, "ulpi", 4)) { reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); } else { /* Relying on default value. */ if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) break; } /* FALLTHROUGH */ case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: ret = dwc3_ulpi_init(dwc); if (ret) return ret; /* FALLTHROUGH */ default: break; } switch (dwc->hsphy_mode) { case USBPHY_INTERFACE_MODE_UTMI: reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); break; case USBPHY_INTERFACE_MODE_UTMIW: reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); break; default: break; } /* * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to * '0' during coreConsultant configuration. So default value will * be '0' when the core is reset. Application needs to set it to * '1' after the core initialization is completed. */ if (dwc->revision > DWC3_REVISION_194A) reg |= DWC3_GUSB2PHYCFG_SUSPHY; if (dwc->dis_u2_susphy_quirk) reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; if (dwc->dis_enblslpm_quirk) reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; if (dwc->dis_u2_freeclk_exists_quirk) reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); return 0; }
/** * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success. The USB PHY interfaces are configured but not * initialized. The PHY interfaces and the PHYs get initialized together with * the core in dwc3_core_init. */ static int dwc3_phy_setup(struct dwc3 *dwc) { u32 reg; int ret; reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); /* * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY * to '0' during coreConsultant configuration. So default value * will be '0' when the core is reset. Application needs to set it * to '1' after the core initialization is completed. */ if (dwc->revision > DWC3_REVISION_194A) reg |= DWC3_GUSB3PIPECTL_SUSPHY; if (dwc->u2ss_inp3_quirk) reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; if (dwc->req_p1p2p3_quirk) reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; if (dwc->del_p1p2p3_quirk) reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; if (dwc->del_phy_power_chg_quirk) reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; if (dwc->lfps_filter_quirk) reg |= DWC3_GUSB3PIPECTL_LFPSFILT; if (dwc->rx_detect_poll_quirk) reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; if (dwc->tx_de_emphasis_quirk) reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); if (dwc->dis_u3_susphy_quirk) reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); /* Select the HS PHY interface */ switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: if (dwc->hsphy_interface && !strncmp(dwc->hsphy_interface, "utmi", 4)) { reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; break; } else if (dwc->hsphy_interface && !strncmp(dwc->hsphy_interface, "ulpi", 4)) { reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); } else { /* Relying on default value. */ if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) break; } /* FALLTHROUGH */ case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: /* Making sure the interface and PHY are operational */ ret = dwc3_soft_reset(dwc); if (ret) return ret; udelay(1); ret = dwc3_ulpi_init(dwc); if (ret) return ret; /* FALLTHROUGH */ default: break; } /* * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to * '0' during coreConsultant configuration. So default value will * be '0' when the core is reset. Application needs to set it to * '1' after the core initialization is completed. */ if (dwc->revision > DWC3_REVISION_194A) reg |= DWC3_GUSB2PHYCFG_SUSPHY; if (dwc->dis_u2_susphy_quirk) reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; if (dwc->dis_enblslpm_quirk) reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); return 0; }
static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) { unsigned long flags; int ret; u32 reg; /* Bring core to D0 state */ dwc3_set_usb_core_power(dwc, true); ret = dwc3_core_init(dwc); if (ret) return ret; switch (dwc->current_dr_role) { case DWC3_GCTL_PRTCAP_DEVICE: ret = dwc3_core_init_for_resume(dwc); if (ret) return ret; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_resume(dwc); spin_unlock_irqrestore(&dwc->lock, flags); break; case DWC3_GCTL_PRTCAP_HOST: if (!PMSG_IS_AUTO(msg)) { ret = dwc3_core_init_for_resume(dwc); if (ret) return ret; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); break; } /* Restore GUSB2PHYCFG bits that were modified in suspend */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); if (dwc->dis_u2_susphy_quirk) reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; if (dwc->dis_enblslpm_quirk) reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); phy_pm_runtime_get_sync(dwc->usb2_generic_phy); phy_pm_runtime_get_sync(dwc->usb3_generic_phy); break; case DWC3_GCTL_PRTCAP_OTG: /* nothing to do on runtime_resume */ if (PMSG_IS_AUTO(msg)) break; ret = dwc3_core_init(dwc); if (ret) return ret; dwc3_set_prtcap(dwc, dwc->current_dr_role); dwc3_otg_init(dwc); if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) { dwc3_otg_host_init(dwc); } else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_resume(dwc); spin_unlock_irqrestore(&dwc->lock, flags); } break; default: /* do nothing */ break; } return 0; }
static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) { unsigned long flags; u32 reg; switch (dwc->current_dr_role) { case DWC3_GCTL_PRTCAP_DEVICE: spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_suspend(dwc); spin_unlock_irqrestore(&dwc->lock, flags); dwc3_core_exit(dwc); break; case DWC3_GCTL_PRTCAP_HOST: if (!PMSG_IS_AUTO(msg)) { dwc3_core_exit(dwc); break; } /* Let controller to suspend HSPHY before PHY driver suspends */ if (dwc->dis_u2_susphy_quirk || dwc->dis_enblslpm_quirk) { reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_ENBLSLPM | DWC3_GUSB2PHYCFG_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); /* Give some time for USB2 PHY to suspend */ usleep_range(5000, 6000); } phy_pm_runtime_put_sync(dwc->usb2_generic_phy); phy_pm_runtime_put_sync(dwc->usb3_generic_phy); break; case DWC3_GCTL_PRTCAP_OTG: /* do nothing during runtime_suspend */ if (PMSG_IS_AUTO(msg)) break; if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_suspend(dwc); spin_unlock_irqrestore(&dwc->lock, flags); } dwc3_otg_exit(dwc); dwc3_core_exit(dwc); break; default: /* do nothing */ break; } dwc3_event_buffers_cleanup(dwc); /* Put the core into D3 state */ dwc3_set_usb_core_power(dwc, false); /* * To avoid reinit of phy during resume, prevent calling the * dwc3_core_exit() when in D3 state */ if (!dwc->is_d3) dwc3_core_exit(dwc); return 0; }