diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c
index 433606f..d034666 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525v2.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c
@@ -47,7 +47,7 @@ static int __out_ep_list_ep0[NUM_OUT_EP + 1] = {0, OUT_EP_LIST};
for(counter = 0, ep = (list)[0]; \
counter < (size); \
counter++, ep = (list)[counter])
-
+
#define FOR_EACH_IN_EP_EX(include_ep0, counter, ep) \
FOR_EACH_EP(include_ep0 ? __in_ep_list_ep0 : __in_ep_list, \
include_ep0 ? NUM_IN_EP + 1: NUM_IN_EP, counter, ep)
@@ -55,7 +55,7 @@ static int __out_ep_list_ep0[NUM_OUT_EP + 1] = {0, OUT_EP_LIST};
#define FOR_EACH_OUT_EP_EX(include_ep0, counter, ep) \
FOR_EACH_EP(include_ep0 ? __out_ep_list_ep0 : __out_ep_list, \
include_ep0 ? NUM_OUT_EP + 1: NUM_OUT_EP, counter, ep)
-
+
#define FOR_EACH_IN_EP(counter, ep) \
FOR_EACH_IN_EP_EX(false, counter, ep)

@@ -99,7 +99,8 @@ enum ep0state
/* endpoints[ep_num][DIR_IN/DIR_OUT] */
static struct usb_endpoint endpoints[USB_NUM_ENDPOINTS][2];
/* setup packet for EP0 */
-static struct usb_ctrlrequest ep0_setup_pkt __attribute__((aligned(32)));
+static struct usb_ctrlrequest _ep0_setup_pkt __attribute__((aligned(32)));
+static struct usb_ctrlrequest *ep0_setup_pkt = AS3525_UNCACHED_ADDR(&_ep0_setup_pkt);
/* state of EP0 */
static enum ep0state ep0_state;

@@ -126,10 +127,11 @@ static void as3525v2_connect(void)
bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE);
usb_delay();
/* 2) enable usb phy clock */
+ CCU_USB = (CCU_USB & ~(3<<24)) | (1 << 24); /* ?? */
/* PHY clock */
CGU_USB = 1<<5 /* enable */
- | (CLK_DIV(AS3525_PLLA_FREQ, 60000000)) << 2
- | 1; /* source = PLLA */
+ | 0 << 2 /* no divider */
+ | 0; /* source = ?? */
usb_delay();
/* 3) clear "stop pclk" */
PCGCCTL &= ~0x1;
@@ -157,9 +159,10 @@ static void as3525v2_connect(void)
GUSBCFG |= GUSBCFG_force_device_mode;
usb_delay();
/* 11) Do something that is probably CCU related but undocumented*/
- CCU_USB &= ~0x1000;
- usb_delay();
- CCU_USB &= ~0x300000;
+ CCU_USB &= ~(1<<12);
+ nop;nop;nop;nop;nop;
+ nop;nop;nop;nop;nop;
+ CCU_USB &= ~(3<<20);
usb_delay();
/* 12) reset usb core parameters (dev addr, speed, ...) */
DCFG = 0;
@@ -190,7 +193,7 @@ static void enable_device_interrupts(void)
static void flush_tx_fifos(int nums)
{
unsigned int i = 0;
-
+
GRSTCTL = (nums << GRSTCTL_txfnum_bitp)
| GRSTCTL_txfflsh_flush;
while(GRSTCTL & GRSTCTL_txfflsh_flush && i < 0x300)
@@ -204,7 +207,7 @@ static void flush_tx_fifos(int nums)
static void flush_rx_fifo(void)
{
unsigned int i = 0;
-
+
GRSTCTL = GRSTCTL_rxfflsh_flush;
while(GRSTCTL & GRSTCTL_rxfflsh_flush && i < 0x300)
i++;
@@ -217,11 +220,7 @@ static void flush_rx_fifo(void)
static void prepare_setup_ep0(void)
{
logf("usb-drv: prepare EP0");
- /* setup DMA */
- //memset(&ep0_setup_pkt, 0, sizeof ep0_setup_pkt);
- //clean_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt); /* force write back */
- clean_dcache();
- DOEPDMA(0) = (unsigned long)AS3525_PHYSICAL_ADDR(&ep0_setup_pkt); /* virtual address=physical address */
+ //memset(ep0_setup_pkt, 0, sizeof *ep0_setup_pkt);

/* Setup EP0 OUT with the following parameters:
* packet count = 1
@@ -230,11 +229,14 @@ static void prepare_setup_ep0(void)
*/
DOEPTSIZ(0) = (1 << DEPTSIZ0_supcnt_bitp)
| (1 << DEPTSIZ0_pkcnt_bitp)
- | 8;
+ | (8 << DEPTSIZ0_xfersize_bitp);
+
+ /* setup DMA */
+ DOEPDMA(0) = (unsigned long)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt);

/* Enable endpoint, clear nak */
ep0_state = EP0_WAIT_SETUP;
- DOEPCTL(0) |= DEPCTL_epena | DEPCTL_cnak;
+ DOEPCTL(0) |= DEPCTL_epena | DEPCTL_usbactep | DEPCTL_cnak;
}

static void handle_ep0_complete(bool is_ack)
@@ -278,7 +280,7 @@ static void handle_ep0_setup(void)
return;
}
/* determine is there is a data phase */
- if(ep0_setup_pkt.wLength == 0)
+ if(ep0_setup_pkt->wLength == 0)
/* no: wait for ack */
ep0_state = EP0_WAIT_ACK;
else
@@ -303,7 +305,7 @@ static void reset_endpoints(void)
else
DIEPCTL(ep) = 0;
}
-
+
FOR_EACH_OUT_EP_AND_EP0(i, ep)
{
endpoints[ep][DIR_OUT].active = false;
@@ -319,7 +321,7 @@ static void reset_endpoints(void)
/* 64 bytes packet size, active endpoint */
DOEPCTL(0) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak;
DIEPCTL(0) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak;
-
+
prepare_setup_ep0();
}

@@ -344,7 +346,7 @@ static void cancel_all_transfers(bool cancel_ep0)
wakeup_signal(&endpoints[ep][DIR_OUT].complete);
DOEPCTL(ep) = (DOEPCTL(ep) & ~DEPCTL_usbactep) | DEPCTL_epdis | DEPCTL_snak;
}
-
+
restore_irq(flags);
}

@@ -354,8 +356,8 @@ static void core_dev_init(void)
/* Restart the phy clock */
PCGCCTL = 0;
/* Set phy speed : high speed */
- DCFG = (DCFG & ~bitm(DCFG, devspd)) | DCFG_devspd_hs_phy_fs;
-
+ DCFG = (DCFG & ~bitm(DCFG, devspd)) | DCFG_devspd_hs_phy_hs;
+
/* Check hardware capabilities */
if(extract(GHWCFG2, arch) != GHWCFG2_ARCH_INTERNAL_DMA)
panicf("usb-drv: wrong architecture (%ld)", extract(GHWCFG2, arch));
@@ -410,7 +412,7 @@ static void core_init(void)
/* Select UTMI+ 16 */
GUSBCFG |= GUSBCFG_phy_if;
GUSBCFG = (GUSBCFG & ~bitm(GUSBCFG, toutcal)) | 7 << GUSBCFG_toutcal_bitp;
-
+
/* fixme: the current code is for internal DMA only, the clip+ architecture
* define the internal DMA model */
/* Set burstlen and enable DMA*/
@@ -421,7 +423,7 @@ static void core_init(void)

/* perform device model specific init */
core_dev_init();
-
+
/* Reconnect */
DCTL &= ~DCTL_sftdiscon;
}
@@ -468,6 +470,9 @@ void usb_drv_exit(void)

static void handle_ep_int(int ep, bool dir_in)
{
+ if (ep)
+ panicf("EP %d %s", ep, dir_in ? "in" : "out");
+
struct usb_endpoint *endpoint = &endpoints[ep][dir_in];
if(dir_in)
{
@@ -482,11 +487,10 @@ static void handle_ep_int(int ep, bool dir_in)
endpoint->status = 0;
/* works even for EP0 */
int transfered = endpoint->len - (DIEPTSIZ(ep) & DEPTSIZ_xfersize_bits);
- logf("len=%d reg=%ld xfer=%d", endpoint->len,
+ panicf("len=%d reg=%ld xfer=%d", endpoint->len,
(DIEPTSIZ(ep) & DEPTSIZ_xfersize_bits),
transfered);
- //invalidate_dcache_range(endpoint->buffer, transfered);
- invalidate_dcache();
+ invalidate_dcache_range(endpoint->buffer, transfered);
//DIEPCTL(ep) |= DEPCTL_snak;
/* handle EP0 state if necessary,
* this is a ack if length is 0 */
@@ -526,11 +530,10 @@ static void handle_ep_int(int ep, bool dir_in)
endpoint->status = 0;
/* works even for EP0 */
int transfered = endpoint->len - (DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits);
- logf("len=%d reg=%ld xfer=%d", endpoint->len,
+ panicf("len=%d reg=%ld xfer=%d", endpoint->len,
(DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits),
transfered);
- //invalidate_dcache_range(endpoint->buffer, transfered);
- invalidate_dcache();
+ invalidate_dcache_range(endpoint->buffer, transfered);
/* handle EP0 state if necessary,
* this is a ack if length is 0 */
if(ep == 0)
@@ -546,6 +549,11 @@ static void handle_ep_int(int ep, bool dir_in)
logf("usb-drv: setup on EP%d OUT", ep);
if(ep != 0)
panicf("usb-drv: setup not on EP0, this is impossible");
+
+ if((DOEPTSIZ(ep) >> DEPTSIZ0_supcnt_bitp & DEPTSIZ0_supcnt_bits) < 2)
+ panicf("CANNOT handle > 1 setup packet in DMA mode");
+
+
if((DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits) != 0)
{
logf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits);
@@ -554,16 +562,16 @@ static void handle_ep_int(int ep, bool dir_in)
else
{
//DOEPCTL(ep) |= DEPCTL_snak;
- /* handle the set address here because of a bug in the usb core */
- //invalidate_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt);
- invalidate_dcache();
/* handle EP0 state */
handle_ep0_setup();
- logf(" rt=%x r=%x", ep0_setup_pkt.bRequestType, ep0_setup_pkt.bRequest);
- if(ep0_setup_pkt.bRequestType == USB_TYPE_STANDARD &&
- ep0_setup_pkt.bRequest == USB_REQ_SET_ADDRESS)
- usb_drv_set_address(ep0_setup_pkt.wValue);
- usb_core_control_request(&ep0_setup_pkt);
+ logf(" rt=%x r=%x", ep0_setup_pkt->bRequestType, ep0_setup_pkt->bRequest);
+
+ /* handle the set address here because of a bug in the usb core */
+ if(ep0_setup_pkt->bRequestType == USB_TYPE_STANDARD &&
+ ep0_setup_pkt->bRequest == USB_REQ_SET_ADDRESS)
+ usb_drv_set_address(ep0_setup_pkt->wValue);
+
+ usb_core_control_request(ep0_setup_pkt);
}
}
/* clear interrupts */
@@ -638,7 +646,7 @@ void INT_USB(void)
{
logf("usb-drv: wake up");
}
-
+
if(sts & GINTMSK_otgintr)
{
logf("usb-drv: otg int");
@@ -654,8 +662,12 @@ void INT_USB(void)
{
panicf("usb-drv: disconnect");
cancel_all_transfers(true);
- usb_enable(false);
+ usb_enable(false);
}
+ sts &= ~(GINTMSK_usbreset | GINTMSK_enumdone | GINTMSK_outepintr | GINTMSK_inepintr);
+ sts &= ~(GINTMSK_otgintr|GINTMSK_usbsuspend|GINTMSK_wkupintr);
+ if(sts)
+ panicf("unhdld 0x%lx", sts);

GINTSTS = sts;
}
@@ -683,6 +695,7 @@ int usb_drv_request_endpoint(int type, int dir)
{
(void) type;
(void) dir;
+ panicf("%s(%d, %d)", __func__, type, dir);
logf("usb-drv: request endpoint (type=%d,dir=%s)", type, dir == USB_DIR_IN ? "IN" : "OUT");
return -1;
}
@@ -703,7 +716,7 @@ static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocki
ep = EP_NUM(ep);
logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, blocking=%d", ep,
len, dir_in, blocking);
-
+
volatile unsigned long *epctl = dir_in ? &DIEPCTL(ep) : &DOEPCTL(ep);
volatile unsigned long *eptsiz = dir_in ? &DIEPTSIZ(ep) : &DOEPTSIZ(ep);
volatile unsigned long *epdma = dir_in ? &DIEPDMA(ep) : &DOEPDMA(ep);
@@ -723,7 +736,7 @@ static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocki

if(dir_in)
logf("GNPTXSTS=%lx", GNPTXSTS);
-
+
endpoint->busy = true;
endpoint->len = len;
endpoint->wait = blocking;
@@ -735,12 +748,11 @@ static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocki
DEPTSIZ = 1 << DEPTSIZ_pkcnt_bitp;
else
DEPTSIZ = (nb_packets << DEPTSIZ_pkcnt_bitp) | len;
- //clean_dcache_range(ptr, len);
- clean_dcache();
+ clean_dcache_range(ptr, len);
DEPDMA = (unsigned long)AS3525_PHYSICAL_ADDR(ptr);

logf("pkt=%d dma=%lx", nb_packets, DEPDMA);
-
+
DEPCTL |= DEPCTL_epena | DEPCTL_cnak | DEPCTL_usbactep;

if(blocking)
@@ -787,16 +799,21 @@ void usb_drv_set_address(int address)

void usb_drv_stall(int ep, bool stall, bool in)
{
- (void) ep;
- (void) stall;
- (void) in;
- logf("usb-drv: %sstall EP%d %s", stall ? "" : "un", ep, in ? "IN" : "OUT");
+ if (stall) {
+ if (in)
+ DIEPCTL(ep) |= DEPCTL_stall;
+ else
+ DOEPCTL(ep) |= DEPCTL_stall;
+ } else {
+ if (in)
+ DIEPCTL(ep) &= ~DEPCTL_stall;
+ else
+ DOEPCTL(ep) &= ~DEPCTL_stall;
+ }
}

bool usb_drv_stalled(int ep, bool in)
{
- (void) ep;
- (void) in;
- return true;
+ return (in ? DIEPCTL(ep) : DOEPCTL(ep)) & DEPCTL_stall;
}