diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2011-12-13 20:38:57 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2011-12-13 20:38:57 +0000 |
commit | a60463e636d62015af48ca865359e6535e691a6f (patch) | |
tree | 4a070317900f02eb24eda62e09a2d111b1f49aea /firmware/target | |
parent | 9e8590ad23e9e40a6adcb34df80fc11f75cfb0cf (diff) |
usb-drv-as3525v2.c: simplify
don't interrupt on unhandled events
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31232 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/as3525/usb-drv-as3525v2.c | 172 |
1 files changed, 50 insertions, 122 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c index 3836825114..c6bade6574 100644 --- a/firmware/target/arm/as3525/usb-drv-as3525v2.c +++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c @@ -89,7 +89,6 @@ static enum ep0state ep0_state; void usb_attach(void) { - logf("%s", __func__); /* Nothing to do */ } @@ -108,68 +107,13 @@ static void flush_tx_fifos(void) static void prepare_setup_ep0(void) { - logf("%s", __func__); - /* setup DMA */ DEPDMA(0, true) = (void*)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt); - - /* Setup EP0 OUT with the following parameters: - * packet count = 1 - * setup packet count = 1 - * transfer size = 8 (setup packet) - */ DEPTSIZ(0, true) = (1 << DEPTSIZ0_supcnt_bitp) | (1 << DEPTSIZ0_pkcnt_bitp) | 8; - - /* Enable endpoint, clear nak */ - ep0_state = EP0_WAIT_SETUP; DEPCTL(0, true) |= DEPCTL_epena | DEPCTL_cnak; -} -static void handle_ep0_complete(bool is_ack) -{ - switch(ep0_state) - { - case EP0_WAIT_SETUP: - panicf("usb-drv: EP0 completion while waiting for SETUP"); - case EP0_WAIT_ACK: - if(is_ack) - /* everything is done, prepare next setup */ - prepare_setup_ep0(); - else - panicf("usb-drv: EP0 data completion while waiting for ACK"); - break; - case EP0_WAIT_DATA: - if(is_ack) - panicf("usb-drv: EP0 ACK while waiting for data completion"); - else - /* everything is done, prepare next setup */ - prepare_setup_ep0(); - break; - case EP0_WAIT_DATA_ACK: - ep0_state = is_ack ? EP0_WAIT_DATA : EP0_WAIT_ACK; - break; - default: - panicf("usb-drv: invalid EP0 state"); - } - logf("usb-drv: EP0 state updated to %d", ep0_state); -} - -static void handle_ep0_setup(void) -{ - if(ep0_state != EP0_WAIT_SETUP) - { - logf("usb-drv: EP0 SETUP while in state %d", ep0_state); - return; - } - /* determine is there is a data phase */ - if(ep0_setup_pkt->wLength == 0) - /* no: wait for ack */ - ep0_state = EP0_WAIT_ACK; - else - /* yes: wait ack and data */ - ep0_state = EP0_WAIT_DATA_ACK; - logf("usb-drv: EP0 state updated to %d", ep0_state); + ep0_state = EP0_WAIT_SETUP; } static void reset_endpoints(void) @@ -200,11 +144,12 @@ static void reset_endpoints(void) int next_ep = in_ep_list[(i + 1) % sizeof(in_ep_list)]; DEPCTL(ep, false) = (DEPCTL(ep, false) & ~bitm(DEPCTL, nextep)) | (next_ep << DEPCTL_nextep_bitp); } + + prepare_setup_ep0(); } static void cancel_all_transfers(bool cancel_ep0) { - logf("%s", __func__); int flags = disable_irq_save(); for (int dir = 0; dir < 2; dir++) @@ -244,11 +189,10 @@ void usb_drv_init(void) GRXFSIZ = 512; GNPTXFSIZ = MAKE_FIFOSIZE_DATA(512); - /* fixme: the current code is for internal DMA only, the clip+ architecture - * define the internal DMA model */ - /* Set burstlen and enable DMA*/ + /* FIXME: the current code is for internal DMA only, the clip+ architecture + * defines the internal DMA model */ GAHBCFG = (GAHBCFG_INT_DMA_BURST_INCR << GAHBCFG_hburstlen_bitp) - | GAHBCFG_dma_enable; + | GAHBCFG_dma_enable | GAHBCFG_glblintrmsk; /* Select UTMI+ 16 */ GUSBCFG = GUSBCFG_force_device_mode | GUSBCFG_phy_if | 7 << GUSBCFG_toutcal_bitp; @@ -291,26 +235,17 @@ void usb_drv_init(void) reset_endpoints(); - prepare_setup_ep0(); - GINTMSK = GINTMSK_usbreset | GINTMSK_enumdone | GINTMSK_inepintr | GINTMSK_outepintr - | GINTMSK_disconnect - | GINTMSK_usbsuspend - | GINTMSK_wkupintr - | GINTMSK_otgintr; + | GINTMSK_disconnect; VIC_INT_ENABLE = INTERRUPT_USB; - GAHBCFG |= GAHBCFG_glblintrmsk; } void usb_drv_exit(void) { - logf("%s", __func__); - - GAHBCFG &= ~GAHBCFG_glblintrmsk; VIC_INT_EN_CLEAR = INTERRUPT_USB; DCTL = DCTL_pwronprgdone | DCTL_sftdiscon; @@ -335,9 +270,25 @@ static void handle_ep_int(int ep, bool out) /* works even for EP0 */ int size = (DEPTSIZ(ep, out) & DEPTSIZ_xfersize_bits); int transfered = endpoint->len - size; - /* handle EP0 state if necessary, this is a ack if length is 0 */ if(ep == 0) - handle_ep0_complete(endpoint->len == 0); + { + bool is_ack = endpoint->len == 0; + switch(ep0_state) + { + case EP0_WAIT_SETUP: + panicf("usb-drv: EP0 completion while waiting for SETUP"); + case EP0_WAIT_DATA_ACK: + ep0_state = is_ack ? EP0_WAIT_DATA : EP0_WAIT_ACK; + break; + case EP0_WAIT_ACK: + case EP0_WAIT_DATA: + if((!is_ack && ep0_state == EP0_WAIT_ACK) || (is_ack && ep0_state == EP0_WAIT_DATA)) + panicf("usb-drv: bad EP0 state"); + + prepare_setup_ep0(); + break; + } + } if (!out) endpoint->len = size; usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, transfered); @@ -371,81 +322,63 @@ static void handle_ep_int(int ep, bool out) } else { - /* handle EP0 state */ - handle_ep0_setup(); + if(ep0_state == EP0_WAIT_SETUP) + { + bool data_phase = ep0_setup_pkt->wLength != 0; + ep0_state = data_phase ? EP0_WAIT_DATA_ACK : EP0_WAIT_ACK; + } + logf(" rt=%x r=%x", ep0_setup_pkt->bRequestType, ep0_setup_pkt->bRequest); - /* handle set address */ + if(ep0_setup_pkt->bRequestType == USB_TYPE_STANDARD && ep0_setup_pkt->bRequest == USB_REQ_SET_ADDRESS) { - /* Set address now */ + /* Set address */ DCFG = (DCFG & ~bitm(DCFG, devadr)) | (ep0_setup_pkt->wValue << DCFG_devadr_bitp); } usb_core_control_request(ep0_setup_pkt); } } - /* clear interrupts */ DEPINT(ep, out) = sts; } -static void handle_ep_ints(void) -{ - logf("usb-drv: ep int"); - - unsigned long daint = DAINT; - - for (int i = 0; i < USB_NUM_ENDPOINTS; i++) - { - if (daint & DAINT_IN_EP(i)) - handle_ep_int(i, false); - if (daint & DAINT_OUT_EP(i)) - handle_ep_int(i, true); - } - - /* write back to clear status */ - DAINT = daint; -} - -/* interrupt service routine */ void INT_USB(void) { /* some bits in GINTSTS can be set even though we didn't enable the interrupt source * so AND it with the actual mask */ unsigned long sts = GINTSTS & GINTMSK; + logf("usb-drv: INT 0x%lx", sts); if(sts & GINTMSK_usbreset) { - logf("usb-drv: bus reset"); - - /* Clear the Remote Wakeup Signalling */ DCTL &= ~DCTL_rmtwkupsig; flush_tx_fifos(); - /* Flush the Learning Queue */ GRSTCTL = GRSTCTL_intknqflsh; - /* Reset Device Address */ DCFG &= ~bitm(DCFG, devadr); reset_endpoints(); - prepare_setup_ep0(); usb_core_bus_reset(); } - if(sts & GINTMSK_enumdone) - logf("usb-drv: enum done: speed %cS", usb_drv_port_speed() ? 'H' : 'F'); - - if(sts & GINTMSK_otgintr) + if(sts & (GINTMSK_outepintr | GINTMSK_inepintr)) { - logf("usb-drv: otg int"); - GOTGINT = 0xffffffff; - } + unsigned long daint = DAINT; - if(sts & (GINTMSK_outepintr | GINTMSK_inepintr)) - handle_ep_ints(); + for (int i = 0; i < USB_NUM_ENDPOINTS; i++) + { + if (daint & DAINT_IN_EP(i)) + handle_ep_int(i, false); + if (daint & DAINT_OUT_EP(i)) + handle_ep_int(i, true); + } + + DAINT = daint; + } if(sts & GINTMSK_disconnect) cancel_all_transfers(true); @@ -484,8 +417,6 @@ static unsigned long usb_drv_mps_by_type(int type) int usb_drv_request_endpoint(int type, int dir) { - logf("usb-drv: request endpoint (type=%d,dir=%s)", type, dir == USB_DIR_IN ? "IN" : "OUT"); - for (unsigned i = 1; i < sizeof((dir == USB_DIR_IN) ? in_ep_list : out_ep_list); i++) { int ep = ((dir == USB_DIR_IN) ? in_ep_list : out_ep_list)[i]; @@ -499,13 +430,11 @@ int usb_drv_request_endpoint(int type, int dir) return ep | dir; } - logf("usb-drv: request failed"); return -1; } void usb_drv_release_endpoint(int ep) { - logf("usb-drv: release EP%d %s", EP_NUM(ep), EP_DIR(ep) == USB_DIR_IN ? "IN" : "OUT"); endpoints[EP_NUM(ep)][EP_DIR(ep)].active = false; } @@ -516,10 +445,9 @@ void usb_drv_cancel_all_transfers() static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in) { - ep = EP_NUM(ep); struct usb_endpoint *endpoint = &endpoints[ep][dir_in]; - logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, busy=%d", ep, len, dir_in, endpoint->busy); + logf("%s(%d, %d, %d) busy=%d", __func__, ep, len, dir_in, endpoint->busy); /* disable interrupts to avoid any race */ int oldlevel = disable_irq_save(); @@ -554,12 +482,13 @@ static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in) int usb_drv_recv(int ep, void *ptr, int len) { - usb_drv_transfer(ep, ptr, len, false); + usb_drv_transfer(EP_NUM(ep), ptr, len, false); return 0; } int usb_drv_send(int ep, void *ptr, int len) { + ep = EP_NUM(ep); struct usb_endpoint *endpoint = &endpoints[ep][1]; endpoint->done = false; usb_drv_transfer(ep, ptr, len, true); @@ -570,7 +499,7 @@ int usb_drv_send(int ep, void *ptr, int len) int usb_drv_send_nonblocking(int ep, void *ptr, int len) { - usb_drv_transfer(ep, ptr, len, true); + usb_drv_transfer(EP_NUM(ep), ptr, len, true); return 0; } @@ -589,7 +518,6 @@ void usb_drv_set_address(int address) void usb_drv_stall(int ep, bool stall, bool in) { - logf("usb-drv: %sstall EP%d %s", stall ? "" : "un", ep, in ? "IN" : "OUT"); if (stall) DEPCTL(ep, !in) |= DEPCTL_stall; else |