forked from xuos/xiuos
Add dwc3_core_init
This commit is contained in:
parent
e6f6d3e1dd
commit
d41cdce316
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue