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); }
/** * dwc3_otg_set_peripheral_regs - reset dwc3 otg registers to peripheral operation. * * This function sets the OTG registers to work in B-Device peripheral mode. * This function should be called just before entering to B-Device mode. * * @w: Pointer to the dwc3 otg workqueue. */ static void dwc3_otg_set_peripheral_regs(struct dwc3_otg *dotg) { u32 reg; struct dwc3 *dwc = dotg->dwc; struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv; if (ext_xceiv && !ext_xceiv->otg_capability) { /* Set OCTL[6](PeriMode) to 1 (peripheral) */ reg = dwc3_readl(dotg->regs, DWC3_OCTL); reg |= DWC3_OTG_OCTL_PERIMODE; dwc3_writel(dotg->regs, DWC3_OCTL, reg); /* * TODO: add more OTG registers writes for PERIPHERAL mode here, * see figure 12-19 B-device flow in dwc3 Synopsis spec */ } else { reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_DEVICE); /* * 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; reg &= ~(DWC3_GCTL_PWRDNSCALEMASK); reg |= DWC3_GCTL_PWRDNSCALE(2); reg &= ~(DWC3_GCTL_SOFITPSYNC); dwc3_writel(dwc->regs, DWC3_GCTL, reg); } }
/** * dwc3_otg_set_host_regs - reset dwc3 otg registers to host operation. * * This function sets the OTG registers to work in A-Device host mode. * This function should be called just before entering to A-Device mode. * * @w: Pointer to the dwc3 otg struct */ static void dwc3_otg_set_host_regs(struct dwc3_otg *dotg) { u32 reg; struct dwc3 *dwc = dotg->dwc; struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv; if (ext_xceiv && !ext_xceiv->otg_capability) { /* Set OCTL[6](PeriMode) to 0 (host) */ reg = dwc3_readl(dotg->regs, DWC3_OCTL); reg &= ~DWC3_OTG_OCTL_PERIMODE; dwc3_writel(dotg->regs, DWC3_OCTL, reg); } else { reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(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 can be suspened. */ reg |= DWC3_GCTL_SOFITPSYNC; /* * 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; reg &= ~(DWC3_GCTL_PWRDNSCALEMASK); reg |= DWC3_GCTL_PWRDNSCALE(2); dwc3_writel(dwc->regs, DWC3_GCTL, 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); }
/** * dwc3_otg_set_host_regs - reset dwc3 otg registers to host operation. * * This function sets the OTG registers to work in A-Device host mode. * This function should be called just before entering to A-Device mode. * * @w: Pointer to the dwc3 otg struct */ static void dwc3_otg_set_host_regs(struct dwc3_otg *dotg) { u32 reg; struct dwc3 *dwc = dotg->dwc; struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv; #ifdef CONFIG_MACH_LGE /* use default qcom,dwc-hsphy-init value for Host Mode */ reg = dwc3_readl(dwc->regs, PARAMETER_OVERRIDE_X_REG); reg &= ~(0x03FFFFFF); reg |= (DEFAULT_HSPHY_INIT & 0x03FFFFFF); dwc3_writel(dwc->regs, PARAMETER_OVERRIDE_X_REG, reg); #endif if (ext_xceiv && !ext_xceiv->otg_capability) { /* Set OCTL[6](PeriMode) to 0 (host) */ reg = dwc3_readl(dotg->regs, DWC3_OCTL); reg &= ~DWC3_OTG_OCTL_PERIMODE; dwc3_writel(dotg->regs, DWC3_OCTL, reg); } else { reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(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 can be suspened. */ reg |= DWC3_GCTL_SOFITPSYNC; /* * 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; reg &= ~(DWC3_GCTL_PWRDNSCALEMASK); reg |= DWC3_GCTL_PWRDNSCALE(2); dwc3_writel(dwc->regs, DWC3_GCTL, 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); /* * 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; 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) { /* * 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. * * Starting with revision 2.50A, GFLADJ_REFCLK_LPM_SEL is used * instead. */ 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); } } }
static int keystone_xhci_phy_suspend(void) { int loop_cnt = 0; struct xhci_hcor *hcor; uint32_t *portsc_1 = NULL; uint32_t *portsc_2 = NULL; u32 val, usb2_pls, usb3_pls, event_q; struct dwc3 *dwc3_reg = keystone.dwc3_reg; /* set register addresses */ hcor = keystone.hcor; /* Bypass Scrambling and Set Shorter Training sequence for simulation */ val = DWC3_GCTL_PWRDNSCALE(0x4b0) | DWC3_GCTL_PRTCAPDIR(0x2); writel(val, &dwc3_reg->g_ctl); /* GUSB2PHYCFG */ val = readl(&dwc3_reg->g_usb2phycfg[0]); /* assert bit 6 (SusPhy) */ val |= DWC3_GUSB2PHYCFG_SUSPHY; writel(val, &dwc3_reg->g_usb2phycfg[0]); /* GUSB3PIPECTL */ val = readl(&dwc3_reg->g_usb3pipectl[0]); /* * assert bit 29 to allow PHY to go to suspend when idle * and cause the USB3 SS PHY to enter suspend mode */ val |= (BIT(29) | DWC3_GUSB3PIPECTL_SUSPHY); writel(val, &dwc3_reg->g_usb3pipectl[0]); /* * Steps necessary to allow controller to suspend even when * VBUS is HIGH: * - Init DCFG[2:0] (DevSpd) to: 1=FS * - Init GEVNTADR0 to point to an eventQ * - Init GEVNTSIZ0 to 0x0100 to specify the size of the eventQ * - Init DCTL::Run_nStop = 1 */ writel(0x00020001, &dwc3_reg->d_cfg); /* TODO: local2global( (Uint32) eventQ )? */ writel((u32)&event_q, &dwc3_reg->g_evnt_buf[0].g_evntadrlo); writel(0, &dwc3_reg->g_evnt_buf[0].g_evntadrhi); writel(0x4, &dwc3_reg->g_evnt_buf[0].g_evntsiz); /* Run */ writel(DWC3_DCTL_RUN_STOP, &dwc3_reg->d_ctl); mdelay(100); /* Wait for USB2 & USB3 PORTSC::PortLinkState to indicate suspend */ portsc_1 = (uint32_t *)(&hcor->portregs[0].or_portsc); portsc_2 = (uint32_t *)(&hcor->portregs[1].or_portsc); usb2_pls = 0; usb3_pls = 0; do { ++loop_cnt; usb2_pls = (readl(portsc_1) & PORT_PLS_MASK) >> 5; usb3_pls = (readl(portsc_2) & PORT_PLS_MASK) >> 5; } while (((usb2_pls != 0x4) || (usb3_pls != 0x4)) && loop_cnt < 1000); if (usb2_pls != 0x4 || usb3_pls != 0x4) { debug("USB suspend failed - PLS USB2=%02x, USB3=%02x\n", usb2_pls, usb3_pls); return -1; } debug("USB2 and USB3 PLS - Disabled, loop_cnt=%d\n", loop_cnt); return 0; }
static void uw_ssusb_pre_init(unsigned int ipq_base) { u32 set_bits, tmp; /* GCTL Reset ON */ writel(0x800, ipq_base + DWC3_SSUSB_REG_GCTL); /* Config SS PHY CTRL */ set_bits = 0; writel(0x80, ipq_base + IPQ_SS_PHY_CTRL_REG); udelay(5); ipq_ssusb_clear_bits32(IPQ_SS_PHY_CTRL_REG, 0x80, ipq_base); udelay(5); /* REF_USE_PAD */ set_bits = 0x0000000; /* USE Internal clock */ set_bits |= IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_LANE0_PWR_PRESENT; set_bits |= IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_REF_SS_PHY_EN; writel(set_bits, ipq_base + IPQ_SS_PHY_CTRL_REG); /* Config HS PHY CTRL */ set_bits = IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_UTMI_OTG_VBUS_VALID; /* * COMMONONN forces xo, bias and pll to stay on during suspend; * Allowing suspend (writing 1) kills Aragorn V1 */ set_bits |= IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_COMMONONN; set_bits |= IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_USE_CLKCORE; set_bits |= IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_FSEL_VAL; /* * If the configuration of clocks is not bypassed in Host mode, * HS PHY suspend needs to be prohibited, otherwise - SS connection fails */ ipq_ssusb_clear_and_set_bits32(IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL, 0, set_bits, ipq_base); /* USB2 PHY Reset ON */ writel(DWC3_SSUSB_REG_GUSB2PHYCFG_PHYSOFTRST, ipq_base + DWC3_SSUSB_REG_GUSB2PHYCFG(0)); /* USB3 PHY Reset ON */ writel(DWC3_SSUSB_REG_GUSB3PIPECTL_PHYSOFTRST, ipq_base + DWC3_SSUSB_REG_GUSB3PIPECTL(0)); udelay(5); /* USB3 PHY Reset OFF */ ipq_ssusb_clear_bits32(DWC3_SSUSB_REG_GUSB3PIPECTL(0), DWC3_SSUSB_REG_GUSB3PIPECTL_PHYSOFTRST, ipq_base); ipq_ssusb_clear_bits32(DWC3_SSUSB_REG_GUSB2PHYCFG(0), DWC3_GUSB2PHYCFG_PHYSOFTRST, ipq_base); udelay(5); /* GCTL Reset OFF */ ipq_ssusb_clear_bits32(DWC3_SSUSB_REG_GCTL, DWC3_GCTL_CORESOFTRESET, ipq_base); udelay(5); if (RX_TERM_VALUE) { dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RTUNE_RTUNE_CTRL_REG, 0, ipq_base); dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RTUNE_DEBUG_REG, 0x0448, ipq_base); dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RTUNE_DEBUG_REG, RX_TERM_VALUE, ipq_base); } if (0 != RX_EQ_VALUE) { /* Values from 1 to 7 */ tmp =0; /* * 1. Fixed EQ setting. This can be achieved as follows: * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 - address 1006 bit 6 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 0- address 1006 bit 7 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 4 (also try setting 3 if possible) - * address 1006 bits 10:8 - please make this a variable, if unchanged the section is not executed * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 - address 1006 bit 11 */ tmp = dwc3_ipq_ssusb_read_phy_reg(DWC3_SSUSB_PHY_RX_OVRD_IN_HI_REG, ipq_base); tmp &= ~((u16)1 << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_EN); tmp |= ((u16)1 << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_EN_OVRD); tmp &= ~((u16) DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_MASK << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ); tmp |= RX_EQ_VALUE << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ; tmp |= 1 << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_OVRD; dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RX_OVRD_IN_HI_REG, tmp, ipq_base); } if ((113 != AMPLITUDE_VALUE) || (21 != TX_DEEMPH_3_5DB)) { tmp = dwc3_ipq_ssusb_read_phy_reg(DWC3_SSUSB_PHY_TX_OVRD_DRV_LO_REG, ipq_base); tmp &= ~DWC3_SSUSB_PHY_TX_DEEMPH_MASK; tmp |= (TX_DEEMPH_3_5DB << DWC3_SSUSB_PHY_TX_DEEMPH_SHIFT); tmp &= ~DWC3_SSUSB_PHY_AMP_MASK; tmp |= AMPLITUDE_VALUE; tmp |= DWC3_SSUSB_PHY_AMP_EN; dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_TX_OVRD_DRV_LO_REG, tmp, ipq_base); } ipq_ssusb_clear_and_set_bits32(IPQ_SS_PHY_PARAM_CTRL_1_REG, 0x7, 0x5, ipq_base); /* XHCI REV */ writel((1 << 2), ipq_base + IPQ_QSCRATCH_GENERAL_CFG); writel(0x0c80c010, ipq_base + DWC3_SSUSB_REG_GUCTL); partial_rx_reset_init(ipq_base); set_bits = 0; /* Test U2EXIT_LFPS */ set_bits |= IPQ_SSUSB_REG_GCTL_U2EXIT_LFPS; ipq_ssusb_clear_and_set_bits32(DWC3_SSUSB_REG_GCTL, 0, set_bits, ipq_base); set_bits = 0; set_bits |= IPQ_SSUSB_REG_GCTL_U2RSTECN; set_bits |= IPQ_SSUSB_REG_GCTL_U2EXIT_LFPS; ipq_ssusb_clear_and_set_bits32(DWC3_SSUSB_REG_GCTL, 0, set_bits, ipq_base); writel(DWC3_GCTL_U2EXIT_LFPS | DWC3_GCTL_SOFITPSYNC | DWC3_GCTL_PRTCAPDIR(1) | DWC3_GCTL_U2RSTECN | DWC3_GCTL_PWRDNSCALE(2), ipq_base + DWC3_GCTL); writel((IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_MPLL_MULTI(0x19) | IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_REF_SS_PHY_EN | IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_LANE0_PWR_PRESENT), ipq_base + IPQ_SS_PHY_CTRL_REG); writel((DWC3_SSUSB_REG_GUSB2PHYCFG_SUSPENDUSB20 | DWC3_SSUSB_REG_GUSB2PHYCFG_ENBLSLPM | DWC3_SSUSB_REG_GUSB2PHYCFG_USBTRDTIM(9)), ipq_base + DWC3_SSUSB_REG_GUSB2PHYCFG(0)); writel(DWC3_SSUSB_REG_GUSB3PIPECTL_ELASTIC_BUFFER_MODE | DWC3_SSUSB_REG_GUSB3PIPECTL_TX_DE_EPPHASIS(1) | DWC3_SSUSB_REG_GUSB3PIPECTL_TX_MARGIN(0)| DWC3_SSUSB_REG_GUSB3PIPECTL_DELAYP1TRANS | DWC3_SSUSB_REG_GUSB3PIPECTL_DELAYP1P2P3(1) | DWC3_SSUSB_REG_GUSB3PIPECTL_U1U2EXITFAIL_TO_RECOV | DWC3_SSUSB_REG_GUSB3PIPECTL_REQUEST_P1P2P3, ipq_base + DWC3_SSUSB_REG_GUSB3PIPECTL(0)); writel(IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_LOS_LEVEL(0x9) | IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_DEEMPH_3_5DB(0x17) | IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_DEEMPH_6DB(0x20) | IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_SWING_FULL(0x6E), ipq_base + IPQ_SS_PHY_PARAM_CTRL_1_REG); writel(IPQ_SSUSB_REG_QSCRATCH_GENERAL_CFG_XHCI_REV(DWC3_SSUSB_XHCI_REV_10), ipq_base + IPQ_QSCRATCH_GENERAL_CFG); }