usb: dwc_otg_310: use wait-till-ready timeout loop for ep deactivate

In some error case, it may fail to set the NAK bit
or Disable bit for endpoint when do ep deactivate
operation. We need to use wait-till-ready timeout
loop for ep deactivate instead of while loop.

Change-Id: I0e5ed61b2528f89910333c5eb907677e492fe3a0
Signed-off-by: William Wu <william.wu@rock-chips.com>
This commit is contained in:
William Wu
2017-11-28 11:43:01 +08:00
committed by Tao Huang
parent 94ddeb4fa9
commit f0cdce4eaa
3 changed files with 68 additions and 61 deletions

View File

@@ -3110,6 +3110,20 @@ void set_pid_isoc(dwc_hc_t *hc)
}
}
int dwc_otg_wait_bit_set(volatile u32 *reg, u32 bit, u32 timeout)
{
int i;
for (i = 0; i < timeout; i++) {
if (DWC_READ_REG32(reg) & bit)
return 0;
dwc_udelay(1);
}
return -ETIMEDOUT;
}
/**
* This function does the setup for a data transfer for a host channel and
* starts the transfer. May be called in either Slave mode or DMA mode. In
@@ -3883,73 +3897,76 @@ void dwc_otg_ep_deactivate(dwc_otg_core_if_t *core_if, dwc_ep_t *ep)
depctl_data_t depctl = {.d32 = 0 };
if (ep->is_in) {
diepint_data_t diepint = {.d32 = 0 };
dwc_otg_dev_in_ep_regs_t *in_ep_reg;
in_ep_reg = core_if->dev_if->in_ep_regs[ep->num];
depctl.b.snak = 1;
DWC_WRITE_REG32(&core_if->dev_if->
in_ep_regs[ep->num]->diepctl,
DWC_WRITE_REG32(&in_ep_reg->diepctl,
depctl.d32);
do {
dwc_udelay(10);
diepint.d32 =
DWC_READ_REG32(&core_if->dev_if->
in_ep_regs[ep->
num]->diepint);
} while (!diepint.b.inepnakeff);
diepint.b.inepnakeff = 1;
DWC_WRITE_REG32(&core_if->dev_if->
in_ep_regs[ep->num]->diepint,
diepint.d32);
if (dwc_otg_wait_bit_set(&in_ep_reg->diepint,
diepint.d32, 1000)) {
DWC_WARN("%s: timeout diepctl.snak\n",
__func__);
} else {
DWC_WRITE_REG32(&in_ep_reg->diepint,
diepint.d32);
}
depctl.d32 = 0;
depctl.b.epdis = 1;
DWC_WRITE_REG32(&core_if->dev_if->
in_ep_regs[ep->num]->diepctl,
DWC_WRITE_REG32(&in_ep_reg->diepctl,
depctl.d32);
do {
dwc_udelay(10);
diepint.d32 =
DWC_READ_REG32(&core_if->dev_if->
in_ep_regs[ep->
num]->diepint);
} while (!diepint.b.epdisabled);
diepint.d32 = 0;
diepint.b.epdisabled = 1;
DWC_WRITE_REG32(&core_if->dev_if->
in_ep_regs[ep->num]->diepint,
diepint.d32);
if (dwc_otg_wait_bit_set(&in_ep_reg->diepint,
diepint.d32, 1000)) {
DWC_WARN("%s: timeout diepctl.epdis\n",
__func__);
} else {
DWC_WRITE_REG32(&in_ep_reg->diepint,
diepint.d32);
}
} else {
dctl_data_t dctl = {.d32 = 0 };
gintmsk_data_t gintsts = {.d32 = 0 };
doepint_data_t doepint = {.d32 = 0 };
dwc_otg_dev_out_ep_regs_t *out_ep_reg;
out_ep_reg = core_if->dev_if->out_ep_regs[ep->num];
dctl.b.sgoutnak = 1;
DWC_MODIFY_REG32(&core_if->dev_if->
dev_global_regs->dctl, 0, dctl.d32);
do {
dwc_udelay(10);
gintsts.d32 =
DWC_READ_REG32(&core_if->core_global_regs->
gintsts);
} while (!gintsts.b.goutnakeff);
DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
0, dctl.d32);
gintsts.d32 = 0;
gintsts.b.goutnakeff = 1;
DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,
gintsts.d32);
if (dwc_otg_wait_bit_set(&core_if->core_global_regs->gintsts,
gintsts.d32, 1000)) {
DWC_WARN("%s: timeout dctl.sgoutnak\n",
__func__);
} else {
DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,
gintsts.d32);
}
depctl.d32 = 0;
depctl.b.epdis = 1;
depctl.b.snak = 1;
DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
doepctl, depctl.d32);
do {
dwc_udelay(10);
doepint.d32 =
DWC_READ_REG32(&core_if->
dev_if->out_ep_regs[ep->
num]->
doepint);
} while (!doepint.b.epdisabled);
DWC_WRITE_REG32(&out_ep_reg->doepctl, depctl.d32);
doepint.b.epdisabled = 1;
DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
doepint, doepint.d32);
if (dwc_otg_wait_bit_set(&out_ep_reg->doepint,
doepint.d32, 1000)) {
DWC_WARN("%s: timeout doepctl.epdis\n",
__func__);
} else {
DWC_WRITE_REG32(&out_ep_reg->doepint,
doepint.d32);
}
dctl.d32 = 0;
dctl.b.cgoutnak = 1;

View File

@@ -1053,6 +1053,11 @@ extern void hc_xfer_timeout(void *ptr);
*/
extern void ep_xfer_timeout(void *ptr);
/*
* This function is called when set register and wait for completion.
*/
int dwc_otg_wait_bit_set(volatile u32 *reg, u32 bit, u32 timeout);
/*
* The following functions are functions for works
* using during handling some interrupts

View File

@@ -1706,21 +1706,6 @@ out_unlocked:
}
static int dwc_otg_wait_bit_set(volatile uint32_t *reg,
uint32_t bit, uint32_t timeout)
{
int i;
for (i = 0; i < timeout; i++) {
if (DWC_READ_REG32(reg) & bit)
return 0;
dwc_udelay(1);
}
return -ETIMEDOUT;
}
static void dwc_otg_pcd_ep_stop_transfer(dwc_otg_core_if_t
*core_if, dwc_ep_t *ep)
{