From c1e454d8190e390838cb93279a2fa328575ce9c4 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Sat, 19 Jun 2010 20:39:32 +0000 Subject: as3525v2-usb: rework thing, simplify git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26967 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/as3525/usb-drv-as3525v2.c | 272 ++++++++++++-------------- firmware/target/arm/as3525/usb-drv-as3525v2.h | 8 +- 2 files changed, 126 insertions(+), 154 deletions(-) (limited to 'firmware') diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c index 37f5798e34..fc6b858755 100644 --- a/firmware/target/arm/as3525/usb-drv-as3525v2.c +++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c @@ -34,6 +34,18 @@ #define LOGF_ENABLE #include "logf.h" #include "usb-drv-as3525v2.h" +#include "usb_core.h" + +static int __in_ep_list[USB_NUM_IN_EP] = {USB_IN_EP_LIST}; +static int __out_ep_list[USB_NUM_OUT_EP] = {USB_OUT_EP_LIST}; + +/* iterate through each in/out ep except EP0 + * 'counter' is the counter, 'ep' is the actual value */ +#define FOR_EACH_IN_EP(counter, ep) \ + for(counter = 0, ep = __in_ep_list[0]; counter < USB_NUM_IN_EP; counter++, ep = __in_ep_list[counter]) + +#define FOR_EACH_OUT_EP(counter, ep) \ + for(counter = 0, ep = __out_ep_list[0]; counter < USB_NUM_OUT_EP; counter++, ep = __out_ep_list[counter]) struct usb_endpoint { @@ -63,7 +75,10 @@ static void usb_delay(void) { int i = 0; while(i < 0x300) + { + asm volatile("nop"); i++; + } } static void as3525v2_connect(void) @@ -110,31 +125,20 @@ static void as3525v2_connect(void) usb_delay(); } -static void usb_enable_common_interrupts(void) -{ - /* Clear any pending otg interrupt */ - USB_GOTGINT = 0xffffffff; - /* Clear any pending interrupt */ - USB_GINTSTS = 0Xffffffff; - /* Enable interrupts */ - USB_GINTMSK = USB_GINTMSK_otgintr - | USB_GINTMSK_conidstschng - | USB_GINTMSK_disconnect; -} - static void usb_enable_device_interrupts(void) { - /* Disable all interrupts */ - USB_GINTMSK = 0; /* Clear any pending interrupt */ USB_GINTSTS = 0xffffffff; - /* Enable common interrupts */ - usb_enable_common_interrupts(); + /* Clear any pending otg interrupt */ + USB_GOTGINT = 0xffffffff; /* Enable interrupts */ - USB_GINTMSK |= USB_GINTMSK_usbreset + USB_GINTMSK = USB_GINTMSK_usbreset | USB_GINTMSK_enumdone | USB_GINTMSK_inepintr - | USB_GINTMSK_outepintr; + | USB_GINTMSK_outepintr + | USB_GINTMSK_otgintr + | USB_GINTMSK_usbsuspend + | USB_GINTMSK_wkupintr; } static void usb_flush_tx_fifos(int nums) @@ -184,6 +188,47 @@ static void core_reset(void) udelay(1); } +static void reset_endpoints(void) +{ + int i, ep; + /* disable all endpoints except EP0 */ + FOR_EACH_IN_EP(i, ep) + if(USB_DIEPCTL(ep) & USB_DEPCTL_epena) + USB_DIEPCTL(ep) = USB_DEPCTL_epdis | USB_DEPCTL_snak; + else + USB_DIEPCTL(ep) = 0; + + FOR_EACH_OUT_EP(i, ep) + if(USB_DOEPCTL(ep) & USB_DEPCTL_epena) + USB_DOEPCTL(ep) = USB_DEPCTL_epdis | USB_DEPCTL_snak; + else + USB_DOEPCTL(ep) = 0; + /* Setup EP0 OUT with the following parameters: + * packet count = 1 + * setup packet count = 1 + * transfer size = 64 + * Setup EP0 IN/OUT with 64 byte maximum packet size and activate both. Enable transfer on EP0 OUT + */ + + /* 64 bytes packet size, active endpoint */ + USB_DOEPCTL(0) = USB_DEPCTL_usbactep | (USB_DEPCTL_MPS_64 << USB_DEPCTL_mps_bit_pos); + + USB_DOEPTSIZ(0) = (1 << USB_DEPTSIZ0_supcnt_bit_pos) + | (1 << USB_DEPTSIZ0_pkcnt_bit_pos) + | 64; + + /* setup DMA */ + clean_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt); /* force write back */ + USB_DOEPDMA(0) = (unsigned long)&ep0_setup_pkt; /* virtual address=physical address */ + + /* Enable endpoint, clear nak */ + USB_DOEPCTL(0) |= USB_DEPCTL_epena | USB_DEPCTL_cnak; + + /* 64 bytes packet size, active endpoint */ + USB_DIEPCTL(0) = (USB_DEPCTL_MPS_64 << USB_DEPCTL_mps_bit_pos) + | USB_DEPCTL_usbactep; +} + static void core_dev_init(void) { unsigned int usb_num_in_ep = 0; @@ -192,9 +237,7 @@ static void core_dev_init(void) /* Restart the phy clock */ USB_PCGCCTL = 0; /* Set phy speed : high speed */ - USB_DCFG = (USB_DCFG & (~USB_DCFG_devspd_bits)) | USB_DCFG_devspd_hs_phy_hs; - /* Set periodic frame interval */ - USB_DCFG = (USB_DCFG & (~USB_DCFG_perfrint_bits)) | (USB_DCFG_FRAME_INTERVAL_80 << USB_DCFG_perfrint_bit_pos); + USB_DCFG = (USB_DCFG & ~USB_DCFG_devspd_bits) | USB_DCFG_devspd_hs_phy_hs; /* Check hardware capabilities */ if(USB_GHWCFG2_ARCH != USB_INT_DMA_ARCH) @@ -208,6 +251,7 @@ static void core_dev_init(void) if(USB_GHWCFG4_DED_FIFO_EN != 1) /* it seems to be multiple tx fifo support */ panicf("usb: no multiple tx fifo"); + /* do some logging */ logf("hwcfg1: %08lx", USB_GHWCFG1); logf("hwcfg2: %08lx", USB_GHWCFG2); logf("hwcfg3: %08lx", USB_GHWCFG3); @@ -233,11 +277,13 @@ static void core_dev_init(void) panicf("usb: num out ep static mismatch(%u,%u)", usb_num_out_ep, USB_NUM_OUT_EP); logf("%d in ep, %d out ep", usb_num_in_ep, usb_num_out_ep); + /* logf("initial:"); logf(" tot fifo sz: %lx", USB_GHWCFG3_DFIFO_LEN); logf(" rx fifo: [%04x,+%4lx]", 0, USB_GRXFSIZ); logf(" nptx fifo: [%04lx,+%4lx]", USB_GET_FIFOSIZE_START_ADR(USB_GNPTXFSIZ), USB_GET_FIFOSIZE_DEPTH(USB_GNPTXFSIZ)); + */ for(i = 1; i <= USB_NUM_IN_EP; i++) { logf(" dieptx fifo(%2u): [%04lx,+%4lx]", i, @@ -253,72 +299,40 @@ static void core_dev_init(void) USB_GRSTCTL = USB_GRSTCTL_intknqflsh; /* Clear all pending device interrupts */ - USB_DIEPMSK = 0; - USB_DOEPMSK = 0; USB_DAINT = 0xffffffff; - USB_DAINTMSK = 0; - - for(i = 0; i <= USB_NUM_IN_EP; i++) - { - /* disable endpoint if enabled */ - if(USB_DIEPCTL(i) & USB_DEPCTL_epena) - USB_DIEPCTL(i) = USB_DEPCTL_epdis | USB_DEPCTL_snak; - else - USB_DIEPCTL(i) = 0; - - USB_DIEPTSIZ(i) = 0; - USB_DIEPDMA(i) = 0; - USB_DIEPINT(i) = 0xff; - } - - for(i = 0; i <= USB_NUM_OUT_EP; i++) - { - /* disable endpoint if enabled */ - if(USB_DOEPCTL(i) & USB_DEPCTL_epena) - USB_DOEPCTL(i) = USB_DEPCTL_epdis | USB_DEPCTL_snak; - else - USB_DOEPCTL(i) = 0; + /* Setup interrupt masks for enpoints */ + /* Setup interrupt masks */ + USB_DOEPMSK = USB_DOEPINT_setup | USB_DOEPINT_xfercompl | USB_DOEPINT_ahberr + | USB_DOEPINT_epdisabled; + USB_DIEPMSK = USB_DIEPINT_xfercompl | USB_DIEPINT_timeout + | USB_DIEPINT_epdisabled | USB_DIEPINT_ahberr + | USB_DIEPINT_intknepmis; + USB_DAINTMSK = 0xffffffff; - USB_DOEPTSIZ(i) = 0; - USB_DOEPDMA(i) = 0; - USB_DOEPINT(i) = 0xff; - } + reset_endpoints(); /* fixme: threshold tweaking only takes place if we use multiple tx fifos it seems */ /* only dump them for now, leave threshold disabled */ + /* logf("threshold control:"); logf(" non_iso_thr_en: %d", (USB_DTHRCTL & USB_DTHRCTL_non_iso_thr_en) ? 1 : 0); logf(" iso_thr_en: %d", (USB_DTHRCTL & USB_DTHRCTL_iso_thr_en) ? 1 : 0); logf(" tx_thr_len: %lu", (USB_DTHRCTL & USB_DTHRCTL_tx_thr_len_bits) >> USB_DTHRCTL_tx_thr_len_bit_pos); logf(" rx_thr_en: %d", (USB_DTHRCTL & USB_DTHRCTL_rx_thr_en) ? 1 : 0); logf(" rx_thr_len: %lu", (USB_DTHRCTL & USB_DTHRCTL_rx_thr_len_bits) >> USB_DTHRCTL_rx_thr_len_bit_pos); + */ /* enable USB interrupts */ usb_enable_device_interrupts(); - - /* enable fifo underrun interrupt ? */ - USB_DIEPMSK |= USB_DIEPINT_txfifoundrn; } static void core_init(void) { - /* Setup phy for high speed */ - USB_GUSBCFG &= ~USB_GUSBCFG_ulpi_ext_vbus_drv; - /* Disable external TS Dline pulsing (???) */ - USB_GUSBCFG &= ~USB_GUSBCFG_term_sel_dl_pulse; - /* core reset */ - core_reset(); - - /* Select UTMI */ - USB_GUSBCFG &= ~USB_GUSBCFG_ulpi_utmi_sel; /* Select UTMI+ 16 */ USB_GUSBCFG |= USB_GUSBCFG_phy_if; /* core reset */ core_reset(); - /* fixme: the linux code does that but the clip+ doesn't use ULPI it seems */ - USB_GUSBCFG &= ~(USB_GUSBCFG_ulpi_fsls | USB_GUSBCFG_ulpi_clk_sus_m); - /* fixme: the current code is for internal DMA only, the clip+ architecture * define the internal DMA model */ /* Set burstlen and enable DMA*/ @@ -327,9 +341,6 @@ static void core_init(void) /* Disable HNP and SRP, not sure it's useful because we already forced dev mode */ USB_GUSBCFG &= ~(USB_GUSBCFG_srpcap | USB_GUSBCFG_hnpcapp); - /* enable basic interrupts */ - usb_enable_common_interrupts(); - /* perform device model specific init */ core_dev_init(); } @@ -351,8 +362,6 @@ void usb_drv_init(void) logf("usb_drv_init"); /* Enable PHY and clocks (but leave pullups disabled) */ as3525v2_connect(); - /* Disable global interrupts */ - usb_disable_global_interrupts(); logf("usb: synopsis id: %lx", USB_GSNPSID); /* Core init */ core_init(); @@ -365,68 +374,12 @@ void usb_drv_exit(void) logf("usb_drv_exit"); } -static void activate_ep0(void) -{ - /* Setup EP0 OUT to receive setup packets and - * EP0 IN to transmit packets - * The setup takes enumeration speed into account - */ - - /* Setup packet size of IN ep based of enumerated speed */ - switch((USB_DSTS & USB_DSTS_enumspd_bits) >> USB_DSTS_enumspd_bit_pos) - { - case USB_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: - case USB_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: - case USB_DSTS_ENUMSPD_FS_PHY_48MHZ: - /* Use 64 bytes packet size */ - USB_DIEPCTL(0) = (USB_DIEPCTL(0) & (~USB_DEPCTL_mps_bits)) - | (USB_DEPCTL_MPS_64 << USB_DEPCTL_mps_bit_pos); - break; - case USB_DSTS_ENUMSPD_LS_PHY_6MHZ: - USB_DIEPCTL(0) = (USB_DIEPCTL(0) & (~USB_DEPCTL_mps_bits)) - | (USB_DEPCTL_MPS_8 << USB_DEPCTL_mps_bit_pos); - break; - default: - panicf("usb: invalid enum speed"); - } - - /* Enable OUT ep for receive */ - //USB_DOEPCTL(0) |= USB_DEPCTL_epena; - - /* Clear non periodic NAK for IN ep */ - USB_DCTL |= USB_DCTL_cgnpinnak; -} - -static void ep0_out_start(void) -{ - /* Setup EP0 OUT with the following parameters: - * packet count = 1 - * setup packet count = 1 - * transfer size = 8 (=sizeof setup packet) - */ - USB_DOEPTSIZ(0) = (1 << USB_DEPTSIZ0_supcnt_bit_pos) - | (1 << USB_DEPTSIZ0_pkcnt_bit_pos) - | 8; - - /* setup DMA */ - clean_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt); /* force write back */ - USB_DOEPDMA(0) = (unsigned long)&ep0_setup_pkt; /* virtual address=physical address */ - - /* enable EP */ - USB_DOEPCTL(0) |= USB_DEPCTL_epena | USB_DEPCTL_usbactep; -} - static bool handle_usb_reset(void) { - unsigned int i; logf("usb: bus reset"); - + /* Clear the Remote Wakeup Signalling */ USB_DCTL &= ~USB_DCTL_rmtwkupsig; - - /* Set NAK for all OUT EPs */ - for(i = 0; i <= USB_NUM_OUT_EP; i++) - USB_DOEPCTL(i) = USB_DEPCTL_snak; /* Flush the NP Tx FIFO */ usb_flush_tx_fifos(0); @@ -434,39 +387,49 @@ static bool handle_usb_reset(void) /* Flush the Learning Queue */ USB_GRSTCTL = USB_GRSTCTL_intknqflsh; - /* Setup interrupt masks */ - USB_DAINTMSK = USB_DAINT_IN_EP(0) | USB_DAINT_OUT_EP(0); - USB_DOEPMSK = USB_DOEPINT_setup | USB_DOEPINT_xfercompl | USB_DOEPINT_ahberr - | USB_DOEPINT_epdisabled; - USB_DIEPMSK = USB_DIEPINT_xfercompl | USB_DIEPINT_timeout - | USB_DIEPINT_epdisabled | USB_DIEPINT_ahberr - | USB_DIEPINT_intknepmis; + reset_endpoints(); /* Reset Device Address */ USB_DCFG &= ~USB_DCFG_devadr_bits; - /* setup EP0 to receive SETUP packets */ - ep0_out_start(); - /* Clear interrupt */ - USB_GINTSTS = USB_GINTMSK_usbreset; + usb_core_bus_reset(); return true; } -static bool handle_enum_done(void) +static bool handle_usb_suspend(void) { - logf("usb: enum done"); + logf("usb: suspend"); + + return true; +} + +static bool handle_wake_up(void) +{ + logf("usb: wake up"); - /* Enable EP0 to receive SETUP packets */ - activate_ep0(); + return true; +} - /* Set USB turnaround time - * fixme: unsure about this */ - //USB_GUSBCFG = (USB_GUSBCFG & ~USB_GUSBCFG_usbtrdtim_bits) | (5 << USB_GUSBCFG_usbtrdtim_bit_pos); - //panicf("usb: turnaround time is %d", (USB_GUSBCFG & USB_GUSBCFG_usbtrdtim_bits) >> USB_GUSBCFG_usbtrdtim_bit_pos); +static bool handle_enum_done(void) +{ + logf("usb: enum done"); - /* Clear interrupt */ - USB_GINTSTS = USB_GINTMSK_enumdone; + /* read speed */ + logf("DSTS: %lx", USB_DSTS); + logf("DOEPCTL0=%lx", USB_DOEPCTL(0)); + logf("DOEPTSIZ=%lx", USB_DOEPTSIZ(0)); + logf("DIEPCTL0=%lx", USB_DIEPCTL(0)); + logf("DOEPMSK=%lx", USB_DOEPMSK); + logf("DIEPMSK=%lx", USB_DIEPMSK); + logf("DAINTMSK=%lx", USB_DAINTMSK); + logf("DAINT=%lx", USB_DAINT); + logf("GINTSTS=%lx", USB_GINTSTS); + logf("GINTMSK=%lx", USB_GINTMSK); + logf("DCTL=%lx", USB_DCTL); + logf("GAHBCFG=%lx", USB_GAHBCFG); + logf("GUSBCFG=%lx", USB_GUSBCFG); + logf("DCFG=%lx", USB_DCFG); return true; } @@ -523,7 +486,6 @@ static void dump_intsts(char *buffer, size_t size, unsigned long sts) /* interrupt service routine */ void INT_USB(void) { - static char buffer[256]; /* 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 = USB_GINTSTS & USB_GINTMSK; @@ -545,8 +507,14 @@ void INT_USB(void) /* device part */ HANDLED_CASE(USB_GINTMSK_usbreset, handle_usb_reset) HANDLED_CASE(USB_GINTMSK_enumdone, handle_enum_done) + HANDLED_CASE(USB_GINTMSK_usbsuspend, handle_usb_suspend) + HANDLED_CASE(USB_GINTMSK_wkupintr, handle_wake_up) + /* HANDLED_CASE(USB_GINTMSK_inepintr, handle_in_ep_int) HANDLED_CASE(USB_GINTMSK_outepintr, handle_out_ep_int) + */ + UNHANDLED_CASE(USB_GINTMSK_outepintr) + UNHANDLED_CASE(USB_GINTMSK_inepintr) /* common part */ UNHANDLED_CASE(USB_GINTMSK_otgintr) @@ -557,15 +525,15 @@ void INT_USB(void) if(sts & ~handled_one) goto Lunhandled; + USB_GINTSTS = USB_GINTSTS; + return; Lunhandled: - dump_intsts(buffer, sizeof buffer, sts); - panicf("unhandled usb int: %lx (%s)", sts, buffer); + panicf("unhandled usb int: %lx", sts); Lerr: - dump_intsts(buffer, sizeof buffer, sts); - panicf("error in usb int: %lx (%s)", sts, buffer); + panicf("error in usb int: %lx", sts); } int usb_drv_port_speed(void) diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.h b/firmware/target/arm/as3525/usb-drv-as3525v2.h index e2932d0dd6..37e8aee1e9 100644 --- a/firmware/target/arm/as3525/usb-drv-as3525v2.h +++ b/firmware/target/arm/as3525/usb-drv-as3525v2.h @@ -363,7 +363,11 @@ * Parameters */ /* Number of IN/OUT endpoints */ -#define USB_NUM_IN_EP 3u -#define USB_NUM_OUT_EP 2u +#define USB_NUM_IN_EP 3 +#define USB_NUM_OUT_EP 2 + +/* List of IN enpoints */ +#define USB_IN_EP_LIST 1, 3, 5 +#define USB_OUT_EP_LIST 2, 4 #endif /* __USB_DRV_AS3525v2_H__ */ -- cgit v1.2.3