diff --git a/firmware/export/config/sansafuze.h b/firmware/export/config/sansafuze.h
index 7e722d6..c85340f 100644
--- a/firmware/export/config/sansafuze.h
+++ b/firmware/export/config/sansafuze.h
@@ -186,13 +186,12 @@

#ifndef BOOTLOADER

-#define USB_HANDLED_BY_OF
-
/* USB On-the-go */
#define CONFIG_USBOTG USBOTG_AS3525

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

diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index 4e1714b..6021556 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -113,6 +113,7 @@ struct vec_int_src vec_int_srcs[] =
{ INT_SRC_NAND, INT_NAND },
{ INT_SRC_I2C_AUDIO, INT_I2C_AUDIO },
{ INT_SRC_AUDIO, INT_AUDIO },
+ { INT_SRC_USB, INT_USB, },
#ifdef HAVE_MULTIDRIVE
{ INT_SRC_MCI0, INT_MCI0 },
#endif
@@ -263,11 +264,11 @@ void system_init(void)
CGU_PLLA = AS3525_PLLA_SETTING;
while(!(CGU_INTCTRL & (1<<0))); /* wait until PLLA is locked */

-#if (AS3525_MCLK_SEL == AS3525_CLK_PLLB)
+//#if (AS3525_MCLK_SEL == AS3525_CLK_PLLB)
CGU_PLLBSUP = 0; /* enable PLLB */
CGU_PLLB = AS3525_PLLB_SETTING;
while(!(CGU_INTCTRL & (1<<1))); /* wait until PLLB is locked */
-#endif
+//#endif

#if CONFIG_CPU == AS3525
/* Set FCLK frequency */
diff --git a/firmware/target/arm/as3525/usb-drv-as3525.c b/firmware/target/arm/as3525/usb-drv-as3525.c
index 496d434..8bb6040 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525.c
@@ -95,6 +95,33 @@
#define USB_USER_CONF4 *((volatile unsigned long*) USB_BASE + 0x2020)
#define USB_USER_CONF5 *((volatile unsigned long*) USB_BASE + 0x2024)

+
+/* register bits */
+
+/* write bits 31..16 */
+#define USB_GPIO_IDDIG_SEL (1<<30)
+#define USB_GPIO_FS_DATA_EXT (1<<29)
+#define USB_GPIO_FS_SE0_EXT (1<<28)
+#define USB_GPIO_FS_XCVR_OWNER (1<<27)
+#define USB_GPIO_TX_ENABLE_N (1<<26)
+#define USB_GPIO_TX_BIT_STUFF_EN (1<<25)
+#define USB_GPIO_BSESSVLD_EXT (1<<24)
+#define USB_GPIO_ASESSVLD_EXT (1<<23)
+#define USB_GPIO_VBUS_VLD_EXT (1<<22)
+#define USB_GPIO_VBUS_VLD_EXT_SEL (1<<21)
+#define USB_GPIO_XO_ON (1<<20)
+#define USB_GPIO_CLK_SEL11 (3<<18)
+#define USB_GPIO_CLK_SEL10 (2<<18)
+#define USB_GPIO_CLK_SEL01 (1<<18)
+#define USB_GPIO_CLK_SEL00 (0<<18)
+#define USB_GPIO_XO_EXT_CLK_ENBN (1<<17)
+#define USB_GPIO_XO_REFCLK_ENB (1<<16)
+/* readronly bits 15..0 */
+#define USB_GPIO_PHY_VBUSDRV (1<<1)
+#define USB_GPIO_HS_INTR (1<<0)
+
+
+
struct usb_endpoint
{
void *buf;
@@ -121,76 +148,79 @@ void usb_drv_init(void)
for(i = 0; i < USB_NUM_ENDPOINTS * 2; i++)
endpoints[i].busy = false;

+ /* length regulator: normal operation */
ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2);
- ascodec_write(AS3517_USB_UTIL, ascodec_read(AS3517_USB_UTIL) & ~(1<<4));
-
- /* PHY part */
- CGU_USB = 1<<5 /* enable */
- | (CLK_DIV(AS3525_PLLA_FREQ, 48000000) / 2) << 2
- | 1; /* source = PLLA */

/* AHB part */
CGU_PERI |= CGU_USB_CLOCK_ENABLE;

- USB_GPIO_CSR = 0x6180000;
- USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */
- USB_DEV_CTRL |= 0x400; /* soft disconnect */
+ /* PHY part */
+ CGU_USB = 1<<5 /* enable */
+ | (CLK_DIV(AS3525_PLLB_FREQ, 48000000) / 2) << 2
+ | 2; /* source = PLLB */

- /* UVDD */
+ /* UVDD on */
ascodec_write(AS3517_USB_UTIL, ascodec_read(AS3517_USB_UTIL) | (1<<4));
- sleep(10); //msleep(100)
+ sleep(HZ/10);

- USB_GPIO_CSR = 0x6180000;
+ USB_GPIO_CSR = USB_GPIO_CLK_SEL10
+ | USB_GPIO_TX_BIT_STUFF_EN
+ | USB_GPIO_TX_ENABLE_N
+ | USB_GPIO_XO_ON
+ | USB_GPIO_IDDIG_SEL;

- USB_GPIO_CSR |= 0x1C00000;
- sleep(1); //msleep(3)
- USB_GPIO_CSR |= 0x200000;
- sleep(1); //msleep(10)
+ /* device init */

- USB_DEV_CTRL |= 0x400; /* soft disconnect */
+ USB_DEV_EP_INTR_MASK = 0xffffffff; /* unmask all flags */
+ USB_DEV_INTR_MASK = 0;

- USB_GPIO_CSR &= ~0x1C00000;
- sleep(1); //msleep(3)
- USB_GPIO_CSR &= ~0x200000;
- sleep(1); //msleep(10)
- USB_DEV_CTRL &= ~0x400; /* clear soft disconnect */
+ USB_DEV_CFG = (1<<1) /* low speed */ |
+ (0<<2) /* remote wakeup */ |
+ (1<<3) /* self powered */ |
+ (0<<5) /* 16 bit phy */ |
+ (1<<6) /* bidir phy */ |
+ (0<<17) /* csr prog */ ;

-#if defined(SANSA_CLIP)
- GPIOA_DIR |= (1<<6);
- GPIOA_PIN(6) = (1<<6);
- GPIOA_DIR &= ~(1<<6); /* restore direction for usb_detect() */
-#elif defined(SANSA_FUZE) || defined(SANSA_E200V2)
- GPIOA_DIR |= (1<<3);
- GPIOA_PIN(3) = (1<<3);
- GPIOA_DIR &= ~(1<<3); /* restore direction for usb_detect() */
-#elif defined(SANSA_C200V2)
- GPIOA_DIR |= (1<<1);
- GPIOA_PIN(1) = (1<<1);
- GPIOA_DIR &= ~(1<<1); /* restore direction for usb_detect() */
-#endif
+ USB_DEV_CTRL = (1<<8) /* burst control */ |
+ (1<<4) /* descriptor update */ |
+ (1<<2) /* dma */ |
+ (1<<10) /* soft disconnect */ |
+ (3 << 16) /* burst len = 8 dwords */;

-#if 0 /* linux */
- USB_DEV_CFG |= (1<<17) /* csr programming */
- | (1<<3) /* self powered */
- | (1<<2); /* remote wakeup */
+ /* control endpoint setup (in/out) */
+ USB_IEP_CTRL(0) = USB_OEP_CTRL(0) = 0;

- USB_DEV_CFG &= ~3; /* high speed */
-#endif
+ USB_IEP_CTRL(0) &= ~(3 << 4); /* control endpoint */
+ USB_OEP_CTRL(0) &= ~(3 << 4); /* control endpoint */

- USB_IEP_CTRL(0) &= (3 << 4); /* control endpoint */
- USB_IEP_DESC_PTR(0) = 0;
+ USB_IEP_TXFSIZE(0) = 32; // full speed
+ USB_IEP_MPS(0) = 64; // max packet size
+ USB_OEP_MPS(0) = 64; //max packet size

- USB_OEP_CTRL(0) &= (3 << 4); /* control endpoint */
- USB_OEP_DESC_PTR(0) = 0;
+ USB_PHY_EP0_INFO = 0 /* number */ |
+ (0<<4) /* direction */ |
+ (0<<5) /* ctrl ep */ |
+ (1<< 7) /* config num */ |
+ (0<<11) /* interface num */ |
+ (0<<15) /* alternat setting number */ |
+ (64 << 19); // max packet size

- USB_DEV_INTR_MASK &= ~0xff; /* unmask all flags */
+ //USB_IEP_CTRL(0) |= (1<<0); // stall bit
+ USB_IEP_CTRL(0) |= (1<<7)|(1<<1); // Set NAK, FLUSH
+ USB_OEP_CTRL(0) |= (1<<8)|(1<<1); // clear NAK, FLUSH

- USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */
+ /* TODO : dma setup */

- VIC_INT_ENABLE = INTERRUPT_USB;
+ USB_DEV_EP_INTR |= (1<<0) | (1<<16); /* clear interrupts */
+ USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 in & out */
+
+ /* unmask status */
+ USB_IEP_STS_MASK(0) &= ~0x1ff0; // bits 12-4: mask for all status
+ USB_OEP_STS_MASK(0) &= ~0x1ff0; // bits 12-4: mask for all status
+
+ USB_DEV_CFG &= ~(1<<10); /* clear soft disconnect */

- USB_IEP_CTRL(0) |= (1<<7); /* set NAK */
- USB_OEP_CTRL(0) |= (1<<7); /* set NAK */
+ VIC_INT_ENABLE = INTERRUPT_USB;
}

void usb_drv_exit(void)
@@ -209,6 +239,7 @@ int usb_drv_port_speed(void)

int usb_drv_request_endpoint(int type, int dir)
{
+ panicf("%s(%d,%d)",__func__,type,dir);
(void) type;
int i = dir == USB_DIR_IN ? 0 : 1;

@@ -227,9 +258,11 @@ int usb_drv_request_endpoint(int type, int dir)
void usb_drv_release_endpoint(int ep)
{
int i = (ep & 0x7f) * 2;
- if(ep & USB_DIR_OUT)
+ if(!(ep & USB_DIR_IN))
i++;
endpoints[i].busy = false;
+
+ ep &= ~USB_DIR_IN;
USB_DEV_EP_INTR_MASK |= (1<<ep) | (1<<(16+ep));
}

@@ -239,19 +272,31 @@ void usb_drv_cancel_all_transfers(void)

int usb_drv_recv(int ep, void *ptr, int len)
{
- (void)ep;(void)ptr;(void)len;
+ panicf("%s(%d,%p,%d)", __func__,ep,ptr,len);
+ int i = (ep & 0x7f) * 2;
+ if(!(ep & USB_DIR_IN))
+ i++;
+
if(ep >= 2)
return -1;

+ (void)ptr;(void)len;
+
return -1;
}

int usb_drv_send(int ep, void *ptr, int len)
{
- (void)ep;(void)ptr;(void)len;
+ panicf("%s(%d,%p,%d)", __func__,ep,ptr,len);
+ int i = (ep & 0x7f) * 2;
+ if(!(ep & USB_DIR_IN))
+ i++;
+
if(ep >= 2)
return -1;

+ (void)ptr;(void)len;
+
return -1;
}

@@ -264,7 +309,37 @@ int usb_drv_send_nonblocking(int ep, void *ptr, int len)
/* interrupt service routine */
void INT_USB(void)
{
- panicf("USB interrupt !");
+ int intr = USB_DEV_INTR;
+ if(intr)
+ {
+ panicf("USB devintr: 0x%x", intr);
+ USB_DEV_INTR = intr;
+ }
+
+ int ep = USB_DEV_EP_INTR; // = 0x10001 (in/out)
+ if(ep)
+ {
+ if(ep & (1<<0)) // ctrl in
+ {
+ panicf("ctrl in 0x%x",USB_IEP_STS(0));
+ }
+ if(ep & (1<<1)) // bulk in
+ {
+ }
+ if(ep & (1<<3)) // intr in
+ {
+ }
+ if(ep & (1<<16)) // ctrl out
+ {
+ panicf("ctrl in 0x%x",USB_OEP_STS(0));
+ }
+ if(ep & (1<<17)) // bulk out
+ {
+ }
+
+ panicf("USB : 0x%x 0x%x", intr, ep);
+ USB_DEV_EP_INTR = ep;
+ }
}

/* (not essential? , not implemented in usb-tcc.c) */