Skip to content

Commit

Permalink
Fixed AT32 OTGv1 driver does not re-enables endpoints on wakeup and o…
Browse files Browse the repository at this point in the history
…ther
  • Loading branch information
HorrorTroll committed Dec 4, 2024
1 parent 52e81b3 commit 5d63474
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 16 deletions.
67 changes: 51 additions & 16 deletions os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@

#endif

#define IRQ_RETRY_MASK (GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_RXFLVL)

/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
Expand Down Expand Up @@ -173,6 +175,20 @@ static void otg_disable_ep(USBDriver *usbp) {
otgp->DAINTMSK = DAINTMSK_OUTEPTMSK(0) | DAINTMSK_INEPTMSK(0);
}

static void otg_enable_ep(USBDriver *usbp) {
at32_otg_t *otgp = usbp->otg;
unsigned i;

for (i = 0; i <= usbp->otgparams->num_endpoints; i++) {
if (usbp->epc[i]->out_state != NULL) {
otgp->DAINTMSK |= DAINTMSK_OUTEPTMSK(i);
}
if (usbp->epc[i]->in_state != NULL) {
otgp->DAINTMSK |= DAINTMSK_INEPTMSK(i);
}
}
}

static void otg_rxfifo_flush(USBDriver *usbp) {
at32_otg_t *otgp = usbp->otg;

Expand Down Expand Up @@ -285,30 +301,36 @@ static void otg_fifo_read_to_buffer(volatile uint32_t *fifop,
* @notapi
*/
static void otg_rxfifo_handler(USBDriver *usbp) {
uint32_t sts, cnt, ep;
uint32_t sts, ep;
size_t n, max;

/* Popping the event word out of the RX FIFO.*/
sts = usbp->otg->GRXSTSP;

/* Event details.*/
cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
ep = (sts & GRXSTSP_EPTNUM_MASK) >> GRXSTSP_EPTNUM_OFF;
n = (size_t)((sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF);
ep = (sts & GRXSTSP_EPTNUM_MASK) >> GRXSTSP_EPTNUM_OFF;

switch (sts & GRXSTSP_PKTSTS_MASK) {
case GRXSTSP_SETUP_DATA:
otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->setup_buf,
cnt, 8);
n, 8);
break;
case GRXSTSP_SETUP_COMP:
break;
case GRXSTSP_OUT_DATA:
max = usbp->epc[ep]->out_state->rxsize - usbp->epc[ep]->out_state->rxcnt;
otg_fifo_read_to_buffer(usbp->otg->FIFO[0],
usbp->epc[ep]->out_state->rxbuf,
cnt,
usbp->epc[ep]->out_state->rxsize -
usbp->epc[ep]->out_state->rxcnt);
usbp->epc[ep]->out_state->rxbuf += cnt;
usbp->epc[ep]->out_state->rxcnt += cnt;
n, max);
if (n < max) {
usbp->epc[ep]->out_state->rxbuf += n;
usbp->epc[ep]->out_state->rxcnt += n;
}
else {
usbp->epc[ep]->out_state->rxbuf += max;
usbp->epc[ep]->out_state->rxcnt += max;
}
break;
case GRXSTSP_OUT_COMP:
break;
Expand Down Expand Up @@ -533,6 +555,9 @@ static void otg_isoc_out_failed_handler(USBDriver *usbp) {
static void usb_lld_serve_interrupt(USBDriver *usbp) {
at32_otg_t *otgp = usbp->otg;
uint32_t sts, src;
unsigned retry = 64U;

irq_retry:

sts = otgp->GINTSTS;
sts &= otgp->GINTMSK;
Expand All @@ -556,6 +581,9 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) {
otgp->PCGCCTL &= ~PCGCCTL_STOPPCLK;
}

/* Re-enable endpoint IRQs if they have been disabled by suspend before.*/
otg_enable_ep(usbp);

/* Clear the Remote Wake-up Signaling.*/
otgp->DCTL &= ~DCTL_RWKUPSIG;

Expand Down Expand Up @@ -598,6 +626,10 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) {
/* Set to zero to un-gate the USB core clocks.*/
otgp->PCGCCTL &= ~PCGCCTL_STOPPCLK;
}

/* Re-enable endpoint irqs if they have been disabled by suspend before. */
otg_enable_ep(usbp);

_usb_wakeup(usbp);
}

Expand All @@ -614,12 +646,6 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) {
otg_isoc_out_failed_handler(usbp);
}

/* Performing the whole FIFO emptying in the ISR, it is advised to keep
this IRQ at a very low priority level.*/
if ((sts & GINTSTS_RXFLVL) != 0U) {
otg_rxfifo_handler(usbp);
}

/* IN/OUT endpoints event handling.*/
src = otgp->DAINT;
if (sts & GINTSTS_OEPTINT) {
Expand Down Expand Up @@ -682,6 +708,15 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) {
otg_epin_handler(usbp, 8);
#endif
}

/* Performing the whole FIFO emptying in the STS, it is advised to keep
this IRQ at a very low priority level.*/
if ((sts & GINTSTS_RXFLVL) != 0U) {
otg_rxfifo_handler(usbp);
}

if ((sts & IRQ_RETRY_MASK) && (--retry > 0U))
goto irq_retry;
}

/*===========================================================================*/
Expand Down Expand Up @@ -1129,7 +1164,7 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
/* Transfer initialization.*/
osp->totsize = osp->rxsize;
if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
osp->rxsize = EP0_MAX_OUTSIZE;
osp->rxsize = EP0_MAX_OUTSIZE;

/* Transaction size is rounded to a multiple of packet size because the
following requirement in the RM:
Expand Down
3 changes: 3 additions & 0 deletions os/hal/ports/AT32/LLD/OTGv1/hal_usb_lld.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,9 @@ struct USBDriver {
*/
#define usb_lld_wakeup_host(usbp) \
do { \
/* Turnings clocks back on (may be required if coming out of suspend
mode).*/ \
(usbp)->otg->PCGCCTL &= ~PCGCCTL_STOPPCLK; \
(usbp)->otg->DCTL |= DCTL_RWKUPSIG; \
/* remote wakeup doesn't trigger the wakeup interrupt, therefore
we use the SOF interrupt to detect resume of the bus.*/ \
Expand Down

0 comments on commit 5d63474

Please sign in to comment.