diff --git a/firmware/SOURCES b/firmware/SOURCES
index ac1a3e1..38e4704 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -373,7 +373,8 @@ target/arm/usb-drv-arc.c
 #elif CONFIG_USBOTG == USBOTG_AS3525
 target/arm/as3525/usb-drv-as3525.c
 #elif CONFIG_USBOTG == USBOTG_AS3525v2
-target/arm/as3525/usb-drv-as3525v2.c
+//target/arm/as3525/usb-drv-as3525v2.c
+target/arm/usb-s3c6400x.c
 #elif CONFIG_USBOTG == USBOTG_ISP1583
 drivers/isp1583.c
 #endif
diff --git a/firmware/export/as3525.h b/firmware/export/as3525.h
index e44b4ed..a421aa1 100644
--- a/firmware/export/as3525.h
+++ b/firmware/export/as3525.h
@@ -530,7 +530,7 @@ CE lines

 /* USB */
 #define USB_NUM_ENDPOINTS 4
-#define USB_DEVBSS_ATTR
+#define USB_DEVBSS_ATTR __attribute__((aligned(32)));

 /* I2SIN registers */

diff --git a/firmware/export/as3525v2.h b/firmware/export/as3525v2.h
index e0c13df..d00db3a 100644
--- a/firmware/export/as3525v2.h
+++ b/firmware/export/as3525v2.h
@@ -36,7 +36,7 @@

 #undef USB_NUM_ENDPOINTS

-#define USB_NUM_ENDPOINTS   6
+#define USB_NUM_ENDPOINTS   5

 #define CCU_USB         (*(volatile unsigned long *)(CCU_BASE + 0x20))

diff --git a/firmware/export/config/sansaclipplus.h b/firmware/export/config/sansaclipplus.h
index 8a0a040..0d53774 100644
--- a/firmware/export/config/sansaclipplus.h
+++ b/firmware/export/config/sansaclipplus.h
@@ -179,8 +179,8 @@

 /* enable these for the experimental usb stack */
 #define HAVE_USBSTACK
-#define USB_HANDLED_BY_OF
-//#define USE_ROCKBOX_USB
+//#define USB_HANDLED_BY_OF
+#define USE_ROCKBOX_USB
 #define USB_VENDOR_ID 0x0781
 #define USB_PRODUCT_ID 0x74d1

diff --git a/firmware/export/config/sansaclipv2.h b/firmware/export/config/sansaclipv2.h
index a39fe3e..776ae5d 100644
--- a/firmware/export/config/sansaclipv2.h
+++ b/firmware/export/config/sansaclipv2.h
@@ -175,8 +175,8 @@

 /* enable these for the experimental usb stack */
 #define HAVE_USBSTACK
-#define USB_HANDLED_BY_OF
-//#define USE_ROCKBOX_USB
+//#define USB_HANDLED_BY_OF
+#define USE_ROCKBOX_USB
 #define USB_VENDOR_ID 0x0781
 #define USB_PRODUCT_ID 0x7435

diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c
index 433606f..e22ece1 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,24 +549,45 @@ 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 0
+            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);
+                panicf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits);
                 prepare_setup_ep0();
             }
             else
+#endif
             {
                 //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();
+                if(ep0_setup_pkt->bRequestType == USB_TYPE_STANDARD &&
+                        ep0_setup_pkt->bRequest == USB_REQ_SET_ADDRESS)
+                {
+                    DCFG = (DCFG & ~bitm(DCFG, devadr)) | (ep0_setup_pkt->wValue<< DCFG_devadr_bitp);
+                }
+
+                static int type=-1, req=-1;
+                if(type != ep0_setup_pkt->bRequestType ||
+                   req  !=ep0_setup_pkt->bRequest)
+                {
+                    type = ep0_setup_pkt->bRequestType;
+                    req  =ep0_setup_pkt->bRequest;
+                    usb_core_control_request(ep0_setup_pkt);
+
+                    static int x = 0;
+                    if(++x > 1)
+                        panicf("  rt=%x r=%x", type, req);
+                }
+
                 /* 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);
+                prepare_setup_ep0();
             }
         }
         /* clear interrupts */
@@ -638,7 +662,7 @@ void INT_USB(void)
     {
         logf("usb-drv: wake up");
     }
-    
+
     if(sts & GINTMSK_otgintr)
     {
         logf("usb-drv: otg int");
@@ -654,8 +678,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 +711,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 +732,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 +752,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 +764,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)
@@ -778,25 +806,26 @@ void usb_drv_set_test_mode(int mode)
 void usb_drv_set_address(int address)
 {
     /* ignore it if addres is already set */
-    if(extract(DCFG, devadr) == 0)
-    {
-        logf("usb-drv: set address %x", address);
-        DCFG = (DCFG & ~bitm(DCFG, devadr)) | (address << DCFG_devadr_bitp);
-    }
+    (void)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;
 }

diff --git a/firmware/target/arm/usb-s3c6400x.c b/firmware/target/arm/usb-s3c6400x.c
index dbba9f3..a24f6c9 100644
--- a/firmware/target/arm/usb-s3c6400x.c
+++ b/firmware/target/arm/usb-s3c6400x.c
@@ -24,8 +24,9 @@
 #include "usb-target.h"
 #include "usb_drv.h"

-#define OTGBASE 0x38800000
-#define PHYBASE 0x3C400000
+#include "as3525v2.h"
+#define OTGBASE 0xC6000000
+//#define PHYBASE 0x3C400000
 #include "usb-s3c6400x.h"

 #include "cpu.h"
@@ -44,13 +45,16 @@ struct ep_type
     bool active;
     bool busy;
     bool done;
+    void *ptr;
     int rc;
     int size;
     struct wakeup complete;
 } ;

 static struct ep_type endpoints[5];
-static struct usb_ctrlrequest ctrlreq USB_DEVBSS_ATTR;
+static struct usb_ctrlrequest _ctrlreq __attribute__((aligned(32)));
+static struct usb_ctrlrequest *ctrlreq = AS3525_UNCACHED_ADDR(&_ctrlreq);
+static char dummy[] = { 0x42, 0x42, 0x42, 0x42, 0x42, 0x42 };

 int usb_drv_port_speed(void)
 {
@@ -72,7 +76,7 @@ static void reset_endpoints(int reinit)
     DOEPCTL0 = 0x8000;  /* EP0 OUT ACTIVE */
     DOEPTSIZ0 = 0x20080040;  /* EP0 OUT Transfer Size:
                                 64 Bytes, 1 Packet, 1 Setup Packet */
-    DOEPDMA0 = (uint32_t)&ctrlreq;
+    DOEPDMA0 = (uint32_t)AS3525_PHYSICAL_ADDR(&_ctrlreq);
     DOEPCTL0 |= 0x84000000;  /* EP0 OUT ENABLE CLEARNAK */
     if (reinit)
     {
@@ -134,16 +138,16 @@ void usb_drv_release_endpoint(int ep)

 static void usb_reset(void)
 {
-    volatile int i;
+    //volatile int i;

     DCTL = 0x802;  /* Soft Disconnect */
-
+#if 0
     OPHYPWR = 0;  /* PHY: Power up */
     ORSTCON = 1;  /* PHY: Assert Software Reset */
     for (i = 0; i < 50; i++);
     ORSTCON = 0;  /* PHY: Deassert Software Reset */
     OPHYCLK = 0;  /* PHY: 48MHz clock */
-
+#endif
     GRSTCTL = 1;  /* OTG: Assert Software Reset */
     while (GRSTCTL & 1);  /* Wait for OTG to ack reset */
     while (!(GRSTCTL & 0x80000000));  /* Wait for OTG AHB master idle */
@@ -151,9 +155,10 @@ static void usb_reset(void)
     GRXFSIZ = 0x00000200;  /* RX FIFO: 512 bytes */
     GNPTXFSIZ = 0x02000200;  /* Non-periodic TX FIFO: 512 bytes */
     GAHBCFG = 0x27;  /* OTG AHB config: Unmask ints, burst length 4, DMA on */
-    GUSBCFG = 0x1408;  /* OTG: 16bit PHY and some reserved bits */
+    GUSBCFG = 0x0008   /* OTG: 16bit PHY and some reserved bits */
+        | (5<<10);

-    DCFG = 4;  /* Address 0 */
+    DCFG = 0;  /* Address 0 */
     DCTL = 0x800;  /* Soft Reconnect */
     DIEPMSK = 0x0D;  /* IN EP interrupt mask */
     DOEPMSK = 0x0D;  /* IN EP interrupt mask */
@@ -164,14 +169,14 @@ static void usb_reset(void)
 }

 /* IRQ handler */
-void INT_USB_FUNC(void)
+void INT_USB(void)
 {
     int i;
     uint32_t ints = GINTSTS;
     uint32_t epints;
     if (ints & 0x1000)  /* bus reset */
     {
-        DCFG = 4;  /* Address 0 */
+        DCFG = 0;  /* Address 0 */
         reset_endpoints(1);
         usb_core_bus_reset();
     }
@@ -180,10 +185,10 @@ void INT_USB_FUNC(void)
     {
         /* Set up the maximum packet sizes accordingly */
         uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64;
-        DIEPCTL1 = (DIEPCTL1 & ~0x000003FF) | maxpacket;
-        DOEPCTL2 = (DOEPCTL2 & ~0x000003FF) | maxpacket;
-        DIEPCTL3 = (DIEPCTL3 & ~0x000003FF) | maxpacket;
-        DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket;
+        DIEPCTL1 = (DIEPCTL1 & ~0x000007FF) | maxpacket;
+        DOEPCTL2 = (DOEPCTL2 & ~0x000007FF) | maxpacket;
+        DIEPCTL3 = (DIEPCTL3 & ~0x000007FF) | maxpacket;
+        DOEPCTL4 = (DOEPCTL4 & ~0x000007FF) | maxpacket;
     }

     if (ints & 0x40000)  /* IN EP event */
@@ -192,7 +197,7 @@ void INT_USB_FUNC(void)
             {
                 if (epints & 1)  /* Transfer completed */
                 {
-                    invalidate_dcache();
+                    //invalidate_dcache();
                     int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF);
                     if (endpoints[i].busy)
                     {
@@ -224,8 +229,10 @@ void INT_USB_FUNC(void)
             {
                 if (epints & 1)  /* Transfer completed */
                 {
-                    invalidate_dcache();
-                    int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF);
+                    int size = (DOEPTSIZ(i) & 0x3FFFF);
+                    int bytes = endpoints[i].size - size;
+                    dump_dcache_range(endpoints[i].ptr, size);
+                    endpoints[i].ptr += bytes;
                     if (endpoints[i].busy)
                     {
                         endpoints[i].busy = false;
@@ -239,17 +246,16 @@ void INT_USB_FUNC(void)
                     panicf("USB: AHB error on OUT EP%d", i);
                 if (epints & 8)  /* SETUP phase done */
                 {
-                    invalidate_dcache();
                     if (i == 0)
                     {
-                        if (ctrlreq.bRequest == 5)
+                        if (ctrlreq->bRequest == 5)
                         {
                             /* Already set the new address here,
                                before passing the packet to the core.
                                See below (usb_drv_set_address) for details. */
-                            DCFG = (DCFG & ~0x7F0) | (ctrlreq.wValue << 4);
+                            DCFG = (DCFG & ~0x7F0) | (ctrlreq->wValue << 4);
                         }
-                        usb_core_control_request(&ctrlreq);
+                        usb_core_control_request(ctrlreq);
                     }
                     else panicf("USB: SETUP done on OUT EP%d!?", i);
                 }
@@ -257,7 +263,7 @@ void INT_USB_FUNC(void)
                 if (!i)
                 {
                     DOEPTSIZ0 = 0x20080040;
-                    DOEPDMA0 = (uint32_t)&ctrlreq;
+                    DOEPDMA0 = (uint32_t)AS3525_PHYSICAL_ADDR(&_ctrlreq);
                     DOEPCTL0 |= 0x84000000;
                 }
                 DOEPINT(i) = epints;
@@ -278,6 +284,7 @@ void usb_drv_set_address(int address)
 static void ep_send(int ep, const void *ptr, int length)
 {
     endpoints[ep].busy = true;
+    endpoints[ep].ptr = ptr;
     endpoints[ep].size = length;
     DIEPCTL(ep) |= 0x8000;  /* EPx OUT ACTIVE */
     int blocksize = usb_drv_port_speed() ? 512 : 64;
@@ -285,20 +292,21 @@ static void ep_send(int ep, const void *ptr, int length)
     if (!length)
     {
         DIEPTSIZ(ep) = 1 << 19;  /* one empty packet */
-        DIEPDMA(ep) = 0x10000000;  /* dummy address */
+        DIEPDMA(ep) = (uint32_t)AS3525_PHYSICAL_ADDR(&dummy[0]);
     }
     else
     {
         DIEPTSIZ(ep) = length | (packets << 19);
-        DIEPDMA(ep) = (uint32_t)ptr;
+        DIEPDMA(ep) = (uint32_t)AS3525_PHYSICAL_ADDR(ptr);
     }
-    clean_dcache();
+    clean_dcache_range(ptr, length);
     DIEPCTL(ep) |= 0x84000000;  /* EPx OUT ENABLE CLEARNAK */
 }

 static void ep_recv(int ep, void *ptr, int length)
 {
     endpoints[ep].busy = true;
+    endpoints[ep].ptr = ptr;
     endpoints[ep].size = length;
     DOEPCTL(ep) &= ~0x20000;  /* EPx UNSTALL */
     DOEPCTL(ep) |= 0x8000;  /* EPx OUT ACTIVE */
@@ -307,14 +315,14 @@ static void ep_recv(int ep, void *ptr, int length)
     if (!length)
     {
         DOEPTSIZ(ep) = 1 << 19;  /* one empty packet */
-        DOEPDMA(ep) = 0x10000000;  /* dummy address */
+        DOEPDMA(ep) = (uint32_t)AS3525_PHYSICAL_ADDR(&dummy[0]);
     }
     else
     {
         DOEPTSIZ(ep) = length | (packets << 19);
-        DOEPDMA(ep) = (uint32_t)ptr;
+        DOEPDMA(ep) = (uint32_t)AS3525_PHYSICAL_ADDR(ptr);
     }
-    clean_dcache();
+    invalidate_dcache_range(ptr, length);
     DOEPCTL(ep) |= 0x84000000;  /* EPx OUT ENABLE CLEARNAK */
 }

@@ -372,15 +380,84 @@ void usb_drv_stall(int endpoint, bool stall, bool in)
     }
 }

+static inline void usb_delay(void)
+{
+    int i = 0;
+    while(i < 0x300)
+    {
+        asm volatile("nop");
+        i++;
+    }
+}
+
+
+static void as3525v2_connect(void)
+{
+    //logf("usb-drv: init as3525v2");
+    /* 1) enable usb core clock */
+    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 */
+        | 0 << 2    /* no divider */
+        | 0;        /* source = ?? */
+    usb_delay();
+    /* 3) clear "stop pclk" */
+    PCGCCTL &= ~0x1;
+    usb_delay();
+    /* 4) clear "power clamp" */
+    PCGCCTL &= ~0x4;
+    usb_delay();
+    /* 5) clear "reset power down module" */
+    PCGCCTL &= ~0x8;
+    usb_delay();
+    /* 6) set "power on program done" */
+    DCTL |= 1<<11; //DCTL_pwronprgdone;
+    usb_delay();
+    /* 7) core soft reset */
+    GRSTCTL |= 1<<0; //GRSTCTL_csftrst;
+    usb_delay();
+    /* 8) hclk soft reset */
+    GRSTCTL |= 1<<1; //GRSTCTL_hsftrst;
+    usb_delay();
+    /* 9) flush and reset everything */
+    GRSTCTL |= 0x3f;
+    usb_delay();
+    /* 10) force device mode*/
+    GUSBCFG &= ~(1<<29);//GUSBCFG_force_host_mode;
+    GUSBCFG |= 1<<30;//GUSBCFG_force_device_mode;
+    usb_delay();
+    /* 11) Do something that is probably CCU related but undocumented*/
+    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;
+    usb_delay();
+}
+
 void usb_drv_init(void)
 {
+    unsigned i;
+    for (i = 0; i < sizeof(endpoints)/sizeof(struct ep_type); i++)
+        wakeup_init(&endpoints[i].complete);
+
     /* Enable USB clock */
-    PWRCON &= ~0x4000;
-    PWRCONEXT &= ~0x800;
-    PCGCCTL = 0;
+    as3525v2_connect();
+    //PWRCON &= ~0x4000;
+    //PWRCONEXT &= ~0x800;
+    //PCGCCTL = 0;

     /* unmask irq */
-    INTMSK |= INTMSK_USB_OTG;
+    //INTMSK |= INTMSK_USB_OTG;
+
+
+    VIC_INT_ENABLE = INTERRUPT_USB;
+    GAHBCFG |= 1;

     /* reset the beast */
     usb_reset();
@@ -390,14 +467,18 @@ void usb_drv_exit(void)
 {
     DCTL = 0x802;  /* Soft Disconnect */

-    ORSTCON = 1;  /* Put the PHY into reset (needed to get current down) */
+    GAHBCFG &= ~1;
+    VIC_INT_EN_CLEAR = INTERRUPT_USB;
+
+    //ORSTCON = 1;  /* Put the PHY into reset (needed to get current down) */
     PCGCCTL = 1;  /* Shut down PHY clock */
-    OPHYPWR = 0xF;  /* PHY: Power down */
+    //OPHYPWR = 0xF;  /* PHY: Power down */

-    PWRCON |= 0x4000;
-    PWRCONEXT |= 0x800;
+    //PWRCON |= 0x4000;
+    //PWRCONEXT |= 0x800;
 }

+#if 0
 void usb_init_device(void)
 {
     unsigned int i;
@@ -411,18 +492,21 @@ void usb_enable(bool on)
     if (on) usb_core_init();
     else usb_core_exit();
 }
+#endif

 void usb_attach(void)
 {
     usb_enable(true);
 }

+#if 0
 int usb_detect(void)
 {
     if (charger_inserted())
         return USB_INSERTED;
     return USB_EXTRACTED;
 }
+#endif

 #else
 void usb_init_device(void)
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index d6c8c6e..cc46851 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -304,6 +304,20 @@ static void set_serial_descriptor(void)
     }
     usb_string_iSerial.bLength = 52;
 }
+#elif defined(HAVE_AS3543)
+static void set_serial_descriptor(void)
+{
+    unsigned char serial[8];
+    short* p = &usb_string_iSerial.wString[1];
+    int i;
+
+    ascodec_readbytes(0x38, 8, serial);
+    for(i = 0; i < 8; i++) {
+        *p++ = hex[(serial[i] >> 4) & 0xF];
+        *p++ = hex[(serial[i] >> 0) & 0xF];
+    }
+    usb_string_iSerial.bLength = 52;
+}
 #elif defined(HAVE_AS3514)
 static void set_serial_descriptor(void)
 {