Add dwc3_core_init

This commit is contained in:
songyanguang 2024-09-12 20:10:15 +08:00
parent e6f6d3e1dd
commit d41cdce316
2 changed files with 168 additions and 1 deletions

View File

@ -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; 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){ int dwc3_alloc_scratch_buffers(struct dwc3 *dwc){
uint32_t len; uint32_t len;
uintptr_t phy_addr, vir_addr; 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){ int dwc3_alloc_event_buffers(struct dwc3 *dwc, uint32_t length){
return 0; return 0;

View File

@ -890,10 +890,18 @@ int dwc3_core_init(struct dwc3 *dwc);
void dwc3_core_exit(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_alloc_scratch_buffers(struct dwc3 *dwc);
int dwc3_setup_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); 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); struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length);