From d41cdce316c0dd2c7693c9439f91aac3dfa134b7 Mon Sep 17 00:00:00 2001 From: songyanguang <345810377@qq.com> Date: Thu, 12 Sep 2024 20:10:15 +0800 Subject: [PATCH] Add dwc3_core_init --- .../drivers/usb/components/port/dwc3/dwc3.c | 161 +++++++++++++++++- .../drivers/usb/components/port/dwc3/dwc3.h | 8 + 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.c b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.c index 17c2c4fbd..bd11f29af 100644 --- a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.c +++ b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.c @@ -87,8 +87,150 @@ void dwc3_cache_hwparams(struct dwc3 *dwc) -int dwc3_core_init(struct dwc3 *dwc){ +/** + * 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) +{ + unsigned long timeout; + uint32_t hwparams4 = dwc->hwparams.hwparams4; + uint32_t reg; + int ret; + + reg = dwc3_readl(dwc->regs_vir, DWC3_GSNPSID); + /* This should read as U3 followed by revision number */ + if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { + USB_LOG_ERR("this is not a DesignWare USB3 DRD Core\n"); + ret = -ENODEV; + goto err0; + } + dwc->revision = reg; + + /* 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 */ + timeout = 5000; + dwc3_writel(dwc->regs_vir, DWC3_DCTL, DWC3_DCTL_CSFTRST); + while (timeout--) { + reg = dwc3_readl(dwc->regs_vir, DWC3_DCTL); + if (!(reg & DWC3_DCTL_CSFTRST)) + break; + }; + + if (!timeout) { + USB_LOG_ERR("Reset Timed Out\n"); + ret = -ETIMEDOUT; + goto err0; + } + + ret = dwc3_core_soft_reset(dwc); + if (ret) + goto err0; + + if (dwc->revision >= DWC3_REVISION_250A) { + reg = dwc3_readl(dwc->regs_vir, DWC3_GUCTL1); + + if (dwc->maximum_speed == USB_SPEED_HIGH || + dwc->maximum_speed == USB_SPEED_FULL) + reg |= DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK; + + dwc3_writel(dwc->regs_vir, DWC3_GUCTL1, reg); + } + + reg = dwc3_readl(dwc->regs_vir, 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: + USB_LOG_DBG("No power optimization available\n"); + } + + /* check if current dwc3 is on simulation board */ + if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { + USB_LOG_DBG("it is on FPGA board\n"); + dwc->is_fpga = true; + } + + if(dwc->disable_scramble_quirk && !dwc->is_fpga) + USB_LOG_WRN("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_vir, DWC3_GCTL, reg); + + dwc3_phy_setup(dwc); + + ret = dwc3_alloc_scratch_buffers(dwc); + if (ret) + goto err0; + + ret = dwc3_setup_scratch_buffers(dwc); + if (ret) + goto err1; + return 0; + +err1: + dwc3_free_scratch_buffers(dwc); + +err0: + return ret; } @@ -96,6 +238,20 @@ void dwc3_core_exit(struct dwc3 *dwc){ } + +int dwc3_core_soft_reset(struct dwc3 *dwc){ + return 0; +} + + +void dwc3_core_num_eps(struct dwc3 *dwc){ +} + + +void dwc3_phy_setup(struct dwc3 *dwc){ +} + + int dwc3_alloc_scratch_buffers(struct dwc3 *dwc){ uint32_t len; uintptr_t phy_addr, vir_addr; @@ -161,6 +317,9 @@ err_cmd: } +void dwc3_free_scratch_buffers(struct dwc3 *dwc){ +} + int dwc3_alloc_event_buffers(struct dwc3 *dwc, uint32_t length){ return 0; diff --git a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.h b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.h index b4e6b06cd..e01ea78bf 100644 --- a/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.h +++ b/Ubiquitous/XiZi_AIoT/services/drivers/usb/components/port/dwc3/dwc3.h @@ -890,10 +890,18 @@ int dwc3_core_init(struct dwc3 *dwc); void dwc3_core_exit(struct dwc3 *dwc); +int dwc3_core_soft_reset(struct dwc3 *dwc); + +void dwc3_core_num_eps(struct dwc3 *dwc); + +void dwc3_phy_setup(struct dwc3 *dwc); + int dwc3_alloc_scratch_buffers(struct dwc3 *dwc); int dwc3_setup_scratch_buffers(struct dwc3 *dwc); +void dwc3_free_scratch_buffers(struct dwc3 *dwc); + int dwc3_alloc_event_buffers(struct dwc3 *dwc, uint32_t length); struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length);