/** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ static int dwc3_core_init(struct dwc3 *dwc) { unsigned long timeout; u32 reg; int ret; reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); /* This should read as U3 followed by revision number */ if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } dwc->revision = reg; /* issue device SoftReset too */ timeout = jiffies + msecs_to_jiffies(500); dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); do { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) break; if (time_after(jiffies, timeout)) { dev_err(dwc->dev, "Reset Timed Out\n"); ret = -ETIMEDOUT; goto err0; } cpu_relax(); } while (true); dwc3_core_soft_reset(dwc); reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; reg &= ~DWC3_GCTL_DISSCRAMBLE; switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { case DWC3_GHWPARAMS1_EN_PWROPT_CLK: reg &= ~DWC3_GCTL_DSBLCLKGTNG; break; default: dev_dbg(dwc->dev, "No power optimization available\n"); } /* * 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 (dwc->revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; dwc3_core_num_eps(dwc); dwc3_writel(dwc->regs, DWC3_GCTL, reg); /* * The default value of GUCTL[31:22] should be 0x8. But on cores * revision < 2.30a, the default value is mistakenly overridden * with 0x0. Restore the correct default value. */ if (dwc->revision < DWC3_REVISION_230A) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL); reg &= ~DWC3_GUCTL_REFCLKPER; reg |= 0x8 << __ffs(DWC3_GUCTL_REFCLKPER); dwc3_writel(dwc->regs, DWC3_GUCTL, reg); } /* * Currently, the default and the recommended value for GUSB3PIPECTL * [21:19] in the RTL is 3'b100 or 32 consecutive errors. Based on * analysis and experiments in the lab, it is found that there is a * relatively low probability of getting 32 consecutive word errors * in the presence of random recovered noise (during electrical idle). * This can delay the entry to a low power state such that for * applications where the link stays in a non-U0 state for a short * duration (< 1 microsecond), the local PHY does not enter the low * power state prior to receiving a potential LFPS wakeup. This causes * the PHY CDR (Clock and Data Recovery) operation to be unstable for * some Synopsys PHYs. * * The proposal now is to change the default and the recommended value * for GUSB3PIPECTL[21:19] in the RTL from 3'b100 to a minimum of * 3'b001. Perform the same in software for controllers prior to 2.30a * revision. */ if (dwc->revision < DWC3_REVISION_230A) { reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_DELAY_P1P2P3; reg |= 1 << __ffs(DWC3_GUSB3PIPECTL_DELAY_P1P2P3); /* * Receiver Detection in U3/Rx.Det is mistakenly disabled in * cores < 2.30a. Fix it here. */ reg &= ~DWC3_GUSB3PIPECTL_DIS_RXDET_U3_RXDET; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); } /* * clear Elastic buffer mode in GUSBPIPE_CTRL(0) register, otherwise * it results in high link errors and could cause SS mode transfer * failure. */ if (!dwc->nominal_elastic_buffer) { reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_ELASTIC_BUF_MODE; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); } return 0; err0: return ret; }
/** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ static int dwc3_core_init(struct dwc3 *dwc) { unsigned long timeout; u32 reg; int ret; struct usb_phy *usb_phy; reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); /* This should read as U3 followed by revision number */ if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } dwc->revision = reg; /* issue device SoftReset too */ timeout = jiffies + msecs_to_jiffies(500); dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); do { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) break; if (time_after(jiffies, timeout)) { dev_err(dwc->dev, "Reset Timed Out\n"); ret = -ETIMEDOUT; goto err0; } cpu_relax(); } while (true); dwc3_core_soft_reset(dwc); /* DCTL core soft reset may cause PHY hang, delay 1 ms and check ulpi */ mdelay(1); if (!dwc->utmi_phy) { usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); if (usb_phy && usb_phy_io_read(usb_phy, ULPI_VENDOR_ID_LOW) < 0) dev_err(dwc->dev, "ULPI not working after DCTL soft reset\n"); usb_put_phy(usb_phy); } reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; reg &= ~DWC3_GCTL_DISSCRAMBLE; switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { case DWC3_GHWPARAMS1_EN_PWROPT_CLK: reg &= ~DWC3_GCTL_DSBLCLKGTNG; break; default: dev_dbg(dwc->dev, "No power optimization available\n"); } /* * 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 (dwc->revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; dwc3_core_num_eps(dwc); dwc3_writel(dwc->regs, DWC3_GCTL, reg); return 0; err0: return ret; }
/** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ static int dwc3_core_init(struct dwc3 *dwc) { unsigned long timeout; u32 hwparams4 = dwc->hwparams.hwparams4; u32 reg; int ret; reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); /* This should read as U3 followed by revision number */ if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } dwc->revision = reg; /* issue device SoftReset too */ timeout = jiffies + msecs_to_jiffies(500); dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); do { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) break; if (time_after(jiffies, timeout)) { dev_err(dwc->dev, "Reset Timed Out\n"); ret = -ETIMEDOUT; goto err0; } cpu_relax(); } while (true); ret = dwc3_core_soft_reset(dwc); if (ret) goto err0; reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; reg &= ~DWC3_GCTL_DISSCRAMBLE; switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { case DWC3_GHWPARAMS1_EN_PWROPT_CLK: /** * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an * issue which would cause xHCI compliance tests to fail. * * Because of that we cannot enable clock gating on such * configurations. * * Refers to: * * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based * SOF/ITP Mode Used */ if ((dwc->dr_mode == USB_DR_MODE_HOST || dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->revision >= DWC3_REVISION_210A && dwc->revision <= DWC3_REVISION_250A)) reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; else reg &= ~DWC3_GCTL_DSBLCLKGTNG; break; case DWC3_GHWPARAMS1_EN_PWROPT_HIB: /* enable hibernation here */ dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); break; default: dev_dbg(dwc->dev, "No power optimization available\n"); } /* * 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 (dwc->revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; dwc3_core_num_eps(dwc); dwc3_writel(dwc->regs, DWC3_GCTL, reg); ret = dwc3_alloc_scratch_buffers(dwc); if (ret) goto err1; ret = dwc3_setup_scratch_buffers(dwc); if (ret) goto err2; return 0; err2: dwc3_free_scratch_buffers(dwc); err1: usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); err0: return ret; }
/** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ static int dwc3_core_init(struct dwc3 *dwc) { u32 reg; int ret; if (!dwc3_core_is_valid(dwc)) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } /* * Write Linux Version Code to our GUID register so it's easy to figure * out which kernel version a bug was found. */ dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); /* Handle USB2.0-only core configuration */ if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { if (dwc->maximum_speed == USB_SPEED_SUPER) dwc->maximum_speed = USB_SPEED_HIGH; } ret = dwc3_core_soft_reset(dwc); if (ret) goto err0; ret = dwc3_phy_setup(dwc); if (ret) goto err0; dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); ret = dwc3_setup_scratch_buffers(dwc); if (ret) goto err1; /* Adjust Frame Length */ dwc3_frame_length_adjustment(dwc); usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); if (ret < 0) goto err2; ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err3; ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); goto err4; } /* * ENDXFER polling is available on version 3.10a and later of * the DWC_usb3 controller. It is NOT available in the * DWC_usb31 controller. */ if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); reg |= DWC3_GUCTL2_RST_ACTBITLATER; dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); } /* * Enable hardware control of sending remote wakeup in HS when * the device is in the L1 state. */ if (dwc->revision >= DWC3_REVISION_290A) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } return 0; err4: phy_power_off(dwc->usb3_generic_phy); err3: phy_power_off(dwc->usb2_generic_phy); err2: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); err1: usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); err0: return ret; }
/** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ static int dwc3_core_init(struct dwc3 *dwc) { u32 hwparams4 = dwc->hwparams.hwparams4; u32 reg; int ret; reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); /* This should read as U3 followed by revision number */ if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { /* Detected DWC_usb3 IP */ dwc->revision = reg; } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { /* Detected DWC_usb31 IP */ dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); dwc->revision |= DWC3_REVISION_IS_DWC31; } else { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } /* * Write Linux Version Code to our GUID register so it's easy to figure * out which kernel version a bug was found. */ dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); /* Handle USB2.0-only core configuration */ if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { if (dwc->maximum_speed == USB_SPEED_SUPER) dwc->maximum_speed = USB_SPEED_HIGH; } /* issue device SoftReset too */ ret = dwc3_soft_reset(dwc); if (ret) goto err0; ret = dwc3_core_soft_reset(dwc); if (ret) goto err0; reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { case DWC3_GHWPARAMS1_EN_PWROPT_CLK: /** * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an * issue which would cause xHCI compliance tests to fail. * * Because of that we cannot enable clock gating on such * configurations. * * Refers to: * * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based * SOF/ITP Mode Used */ if ((dwc->dr_mode == USB_DR_MODE_HOST || dwc->dr_mode == USB_DR_MODE_OTG) && (dwc->revision >= DWC3_REVISION_210A && dwc->revision <= DWC3_REVISION_250A)) reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; else reg &= ~DWC3_GCTL_DSBLCLKGTNG; break; case DWC3_GHWPARAMS1_EN_PWROPT_HIB: /* enable hibernation here */ dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); /* * REVISIT Enabling this bit so that host-mode hibernation * will work. Device-mode hibernation is not yet implemented. */ reg |= DWC3_GCTL_GBLHIBERNATIONEN; break; default: dwc3_trace(trace_dwc3_core, "No power optimization available\n"); } /* check if current dwc3 is on simulation board */ if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { dwc3_trace(trace_dwc3_core, "running on FPGA platform\n"); dwc->is_fpga = true; } WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, "disable_scramble cannot be used on non-FPGA builds\n"); if (dwc->disable_scramble_quirk && dwc->is_fpga) reg |= DWC3_GCTL_DISSCRAMBLE; else reg &= ~DWC3_GCTL_DISSCRAMBLE; if (dwc->u2exit_lfps_quirk) reg |= DWC3_GCTL_U2EXIT_LFPS; /* * 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 (dwc->revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; dwc3_core_num_eps(dwc); dwc3_writel(dwc->regs, DWC3_GCTL, reg); ret = dwc3_alloc_scratch_buffers(dwc); if (ret) goto err1; ret = dwc3_setup_scratch_buffers(dwc); if (ret) goto err2; return 0; err2: dwc3_free_scratch_buffers(dwc); err1: usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); err0: return ret; }
/** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ int dwc3_core_init(struct dwc3 *dwc) { u32 reg; int ret; if (!dwc3_core_is_valid(dwc)) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } /* * Write Linux Version Code to our GUID register so it's easy to figure * out which kernel version a bug was found. */ dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); /* Handle USB2.0-only core configuration */ if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { if (dwc->maximum_speed == USB_SPEED_SUPER) dwc->maximum_speed = USB_SPEED_HIGH; } ret = dwc3_phy_setup(dwc); if (ret) goto err0; if (!dwc->ulpi_ready) { ret = dwc3_core_ulpi_init(dwc); if (ret) goto err0; dwc->ulpi_ready = true; } if (!dwc->phys_ready) { ret = dwc3_core_get_phy(dwc); if (ret) goto err0a; dwc->phys_ready = true; } ret = dwc3_core_soft_reset(dwc); if (ret) goto err0a; dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); if (dwc->scratchbuf == NULL) { ret = dwc3_alloc_scratch_buffers(dwc); if (ret) { dev_err(dwc->dev, "Not enough memory for scratch buffers\n"); goto err1; } } ret = dwc3_setup_scratch_buffers(dwc); if (ret) { dev_err(dwc->dev, "Failed to setup scratch buffers: %d\n", ret); goto err1; } /* Adjust Frame Length */ dwc3_frame_length_adjustment(dwc); dwc3_set_incr_burst_type(dwc); ret = dwc3_config_soc_bus(dwc); if (ret) goto err1; usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); if (ret < 0) goto err2; ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err3; ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); goto err4; } switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); break; case USB_DR_MODE_HOST: dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); break; case USB_DR_MODE_OTG: dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG); break; default: dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode); break; } /* * ENDXFER polling is available on version 3.10a and later of * the DWC_usb3 controller. It is NOT available in the * DWC_usb31 controller. */ if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); reg |= DWC3_GUCTL2_RST_ACTBITLATER; dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); } /* When configured in HOST mode, after issuing U3/L2 exit controller * fails to send proper CRC checksum in CRC5 feild. Because of this * behaviour Transaction Error is generated, resulting in reset and * re-enumeration of usb device attached. Enabling bit 10 of GUCTL1 * will correct this problem */ if (dwc->enable_guctl1_resume_quirk) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); reg |= DWC3_GUCTL1_RESUME_QUIRK; dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } /* SNPS controller when configureed in HOST mode maintains Inter Packet * Delay (IPD) of ~380ns which works with most of the super-speed hubs * except VIA-LAB hubs. When IPD is ~380ns HOST controller fails to * enumerate FS/LS devices when connected behind VIA-LAB hubs. * Enabling bit 9 of GUCTL1 enables the workaround in HW to reduce the * ULPI clock latency by 1 cycle, thus reducing the IPD (~360ns) and * making controller enumerate FS/LS devices connected behind VIA-LAB. */ if (dwc->enable_guctl1_ipd_quirk) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); reg |= DWC3_GUCTL1_IPD_QUIRK; dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } if (dwc->revision >= DWC3_REVISION_250A) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); /* * Enable hardware control of sending remote wakeup * in HS when the device is in the L1 state. */ if (dwc->revision >= DWC3_REVISION_290A) reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; if (dwc->dis_tx_ipgap_linecheck_quirk) reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } if (dwc->dr_mode == USB_DR_MODE_HOST || dwc->dr_mode == USB_DR_MODE_OTG) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL); /* * Enable Auto retry Feature to make the controller operating in * Host mode on seeing transaction errors(CRC errors or internal * overrun scenerios) on IN transfers to reply to the device * with a non-terminating retry ACK (i.e, an ACK transcation * packet with Retry=1 & Nump != 0) */ reg |= DWC3_GUCTL_HSTINAUTORETRY; dwc3_writel(dwc->regs, DWC3_GUCTL, reg); } /* * Must config both number of packets and max burst settings to enable * RX and/or TX threshold. */ if (dwc3_is_usb31(dwc) && dwc->dr_mode == USB_DR_MODE_HOST) { u8 rx_thr_num = dwc->rx_thr_num_pkt_prd; u8 rx_maxburst = dwc->rx_max_burst_prd; u8 tx_thr_num = dwc->tx_thr_num_pkt_prd; u8 tx_maxburst = dwc->tx_max_burst_prd; if (rx_thr_num && rx_maxburst) { reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); reg |= DWC31_RXTHRNUMPKTSEL_PRD; reg &= ~DWC31_RXTHRNUMPKT_PRD(~0); reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num); reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0); reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst); dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); } if (tx_thr_num && tx_maxburst) { reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG); reg |= DWC31_TXTHRNUMPKTSEL_PRD; reg &= ~DWC31_TXTHRNUMPKT_PRD(~0); reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num); reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0); reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst); dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg); } } return 0; err4: phy_power_off(dwc->usb3_generic_phy); err3: phy_power_off(dwc->usb2_generic_phy); err2: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); err1: usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); err0a: dwc3_ulpi_exit(dwc); err0: return ret; }