usb-drv-as3525v2: simplify usb_reset isr

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31243 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Rafaël Carré 2011-12-14 06:30:36 +00:00
parent 26b31f1a17
commit e062c7a6c3

View file

@ -92,19 +92,6 @@ void usb_attach(void)
/* Nothing to do */ /* Nothing to do */
} }
static void flush_tx_fifos(void)
{
unsigned int i = 0;
GRSTCTL = (0x10 << GRSTCTL_txfnum_bitp) | GRSTCTL_txfflsh_flush;
while(GRSTCTL & GRSTCTL_txfflsh_flush)
if (i++ >= 0x300)
panicf("usb-drv: hang of flush tx fifos");
/* wait 3 phy clocks */
udelay(1);
}
static void prepare_setup_ep0(void) static void prepare_setup_ep0(void)
{ {
DEPDMA(0, true) = (void*)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt); DEPDMA(0, true) = (void*)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt);
@ -122,10 +109,12 @@ static void reset_endpoints(void)
for (unsigned i = 0; i < sizeof((dir == DIR_IN) ? in_ep_list : out_ep_list); i++) for (unsigned i = 0; i < sizeof((dir == DIR_IN) ? in_ep_list : out_ep_list); i++)
{ {
int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i]; int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i];
endpoints[ep][dir == DIR_OUT].active = false; endpoints[ep][dir == DIR_OUT] = (struct usb_endpoint) {
endpoints[ep][dir == DIR_OUT].busy = false; .active = false,
endpoints[ep][dir == DIR_OUT].status = -1; .busy = false,
endpoints[ep][dir == DIR_OUT].done = false; .status = -1,
.done = false,
};
semaphore_release(&endpoints[ep][dir == DIR_OUT].complete); semaphore_release(&endpoints[ep][dir == DIR_OUT].complete);
if (i != 0) if (i != 0)
@ -136,7 +125,6 @@ static void reset_endpoints(void)
DEPCTL(0, dir == DIR_OUT) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak; DEPCTL(0, dir == DIR_OUT) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak;
} }
/* Setup next chain for IN eps */ /* Setup next chain for IN eps */
for (unsigned i = 0; i < sizeof(in_ep_list); i++) for (unsigned i = 0; i < sizeof(in_ep_list); i++)
{ {
@ -156,9 +144,11 @@ static void cancel_all_transfers(bool cancel_ep0)
for (unsigned i = !!cancel_ep0; i < sizeof((dir == DIR_IN) ? in_ep_list : out_ep_list); i++) for (unsigned i = !!cancel_ep0; i < sizeof((dir == DIR_IN) ? in_ep_list : out_ep_list); i++)
{ {
int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i]; int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i];
endpoints[ep][dir == DIR_OUT].status = -1; endpoints[ep][dir == DIR_OUT] = (struct usb_endpoint) {
endpoints[ep][dir == DIR_OUT].busy = false; .status = -1,
endpoints[ep][dir == DIR_OUT].done = false; .busy = false,
.done = false,
};
semaphore_release(&endpoints[ep][dir == DIR_OUT].complete); semaphore_release(&endpoints[ep][dir == DIR_OUT].complete);
DEPCTL(ep, dir) = (DEPCTL(ep, dir) & ~DEPCTL_usbactep) | DEPCTL_snak; DEPCTL(ep, dir) = (DEPCTL(ep, dir) & ~DEPCTL_usbactep) | DEPCTL_snak;
} }
@ -259,6 +249,7 @@ static void handle_ep_int(int ep, bool out)
{ {
struct usb_endpoint *endpoint = &endpoints[ep][out ? DIR_OUT : DIR_IN]; struct usb_endpoint *endpoint = &endpoints[ep][out ? DIR_OUT : DIR_IN];
unsigned long sts = DEPINT(ep, out); unsigned long sts = DEPINT(ep, out);
logf("%s(%d %s): sts = 0x%lx", __func__, ep, out?"OUT":"IN", sts);
if(sts & DEPINT_ahberr) if(sts & DEPINT_ahberr)
panicf("usb-drv: ahb error on EP%d %s", ep, out ? "OUT" : "IN"); panicf("usb-drv: ahb error on EP%d %s", ep, out ? "OUT" : "IN");
if(sts & DEPINT_xfercompl) if(sts & DEPINT_xfercompl)
@ -296,23 +287,12 @@ static void handle_ep_int(int ep, bool out)
semaphore_release(&endpoint->complete); semaphore_release(&endpoint->complete);
} }
} }
if(!out && (sts & DIEPINT_timeout)) if(!out && (sts & DIEPINT_timeout))
{
panicf("usb-drv: timeout on EP%d IN", ep); panicf("usb-drv: timeout on EP%d IN", ep);
if(endpoint->busy)
{
endpoint->busy = false;
endpoint->status = -1;
/* for safety, act as if no bytes as been transfered */
endpoint->len = 0;
usb_core_transfer_complete(ep, USB_DIR_IN, 1, 0);
endpoint->done = true;
semaphore_release(&endpoint->complete);
}
}
if(out && (sts & DOEPINT_setup)) if(out && (sts & DOEPINT_setup))
{ {
logf("usb-drv: setup on EP%d OUT", ep);
if(ep != 0) if(ep != 0)
panicf("usb-drv: setup not on EP0, this is impossible"); panicf("usb-drv: setup not on EP0, this is impossible");
if((DEPTSIZ(ep, true) & DEPTSIZ_xfersize_bits) != 0) if((DEPTSIZ(ep, true) & DEPTSIZ_xfersize_bits) != 0)
@ -352,16 +332,8 @@ void INT_USB(void)
if(sts & GINTMSK_usbreset) if(sts & GINTMSK_usbreset)
{ {
DCTL &= ~DCTL_rmtwkupsig; DCFG &= ~bitm(DCFG, devadr); /* Address 0 */
flush_tx_fifos();
GRSTCTL = GRSTCTL_intknqflsh;
DCFG &= ~bitm(DCFG, devadr);
reset_endpoints(); reset_endpoints();
usb_core_bus_reset(); usb_core_bus_reset();
} }
@ -445,16 +417,14 @@ void usb_drv_cancel_all_transfers()
static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in) static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in)
{ {
struct usb_endpoint *endpoint = &endpoints[ep][dir_in];
logf("%s(%d, %d, %d) busy=%d", __func__, ep, len, dir_in, endpoint->busy);
/* disable interrupts to avoid any race */ /* disable interrupts to avoid any race */
int oldlevel = disable_irq_save(); int oldlevel = disable_irq_save();
endpoint->busy = true; endpoints[ep][dir_in] = (struct usb_endpoint) {
endpoint->len = len; .busy = true,
endpoint->status = -1; .len = len,
.status = -1,
};
DEPCTL(ep, !dir_in) = (DEPCTL(ep, !dir_in) & ~DEPCTL_stall) | DEPCTL_usbactep; DEPCTL(ep, !dir_in) = (DEPCTL(ep, !dir_in) & ~DEPCTL_stall) | DEPCTL_usbactep;