Index: firmware/export/mc13783.h
===================================================================
--- firmware/export/mc13783.h	(revision 17109)
+++ firmware/export/mc13783.h	(working copy)
@@ -104,8 +104,10 @@
 #define MC13783_LOBATL      (1 << 13)
 #define MC13783_LOBATH      (1 << 14)
 #define MC13783_UDP         (1 << 15)
-#define MC13783_USB         (1 << 16)
-#define MC13783_ID          (1 << 19)
+#define MC13783_USB4V4      (1 << 16)
+#define MC13783_USB2V0      (1 << 17)
+#define MC13783_USB0V8      (1 << 18)
+#define MC13783_IDFLOAT     (1 << 19)
 #define MC13783_SE1         (1 << 21)
 #define MC13783_CKDET       (1 << 22)
 #define MC13783_UDM         (1 << 23)
Index: firmware/export/config-gigabeat-s.h
===================================================================
--- firmware/export/config-gigabeat-s.h	(revision 17109)
+++ firmware/export/config-gigabeat-s.h	(working copy)
@@ -112,8 +112,18 @@
 #define CPU_FREQ 16934400
 
 /* define this if the unit can be powered or charged via USB */
-#define HAVE_USB_POWER
+//#define HAVE_USB_POWER
 
+/* USB On-the-go */
+#define CONFIG_USBOTG USBOTG_ARC
+
+/* enable these for the experimental usb stack */
+#define USE_ROCKBOX_USB
+#define HAVE_USBSTACK
+#define USB_STORAGE
+#define USB_VENDOR_ID 0x0930
+#define USB_PRODUCT_ID 0x0010
+
 /* Define this if you have ATA power-off control */
 #define HAVE_ATA_POWER_OFF
 
Index: firmware/export/imx31l.h
===================================================================
--- firmware/export/imx31l.h	(revision 17109)
+++ firmware/export/imx31l.h	(working copy)
@@ -32,6 +32,10 @@
 #define LCD_BUFFER_SIZE ((320*240*2))
 #define TTB_SIZE (0x4000)
 #define TTB_BASE ((unsigned int *)TTB_BASE_ADDR)
+#define UNCACHED_ADDR(x)  \
+({ uintptr_t _x_ = (uintptr_t)(x); \
+   _x_ += _x_ < 0x100000 ? 0x80000000 : 0x80100000; \
+   (typeof(x))_x_; })
 
 /*
  * AIPS 1
@@ -1032,4 +1036,6 @@
 #define writew(v,a)             (*(REG16_PTR_T)(a) = (v))
 #define readw(a)                (*(REG16_PTR_T)(a))
 
+#define USB_BASE                OTG_BASE_ADDR
+
 #endif /* __IMX31L_H__ */
Index: firmware/SOURCES
===================================================================
--- firmware/SOURCES	(revision 17109)
+++ firmware/SOURCES	(working copy)
@@ -233,7 +233,7 @@
 usbstack/usb_core.c
 usbstack/usb_storage.c
 usbstack/usb_serial.c
-#ifdef CPU_PP502x
+#if defined(CPU_PP502x) || CONFIG_CPU == IMX31L
 target/arm/usb-drv-pp502x.c
 #endif
 #else /* !defined(HAVE_USBSTACK) */
Index: firmware/target/arm/usb-drv-pp502x.c
===================================================================
--- firmware/target/arm/usb-drv-pp502x.c	(revision 17109)
+++ firmware/target/arm/usb-drv-pp502x.c	(working copy)
@@ -26,6 +26,11 @@
 //#define LOGF_ENABLE
 #include "logf.h"
 
+#if CONFIG_CPU == IMX31L
+#include "avic-imx31.h"
+void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void);
+#endif
+
 /* USB device mode registers (Little Endian) */
 
 #define REG_ID               (*(volatile unsigned int *)(USB_BASE+0x000))
@@ -354,13 +359,21 @@
 void usb_drv_init(void)
 {
     REG_USBCMD &= ~USBCMD_RUN;
+#if CONFIG_CPU == IMX31L
+    sleep(HZ/20);
+#else
     udelay(50000);
+#endif
     REG_USBCMD |= USBCMD_CTRL_RESET;
     while (REG_USBCMD & USBCMD_CTRL_RESET);
 
-
     REG_USBMODE = USBMODE_CTRL_MODE_DEVICE;
 
+#if CONFIG_CPU == IMX31L
+    /* Set to ULPI */
+    REG_PORTSC1 = (REG_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | (0x2 << 30);
+#endif
+
 #ifndef USE_HIGH_SPEED
     /* Force device to full speed */
     /* See 32.9.5.9.2 */
@@ -383,13 +396,16 @@
         USBINTR_RESET_EN |
         USBINTR_SYS_ERR_EN;
 
+#if CONFIG_CPU == IMX31L
+    avic_enable_int(USB_OTG, IRQ, 7, USB_OTG_HANDLER);
+#else
     /* enable USB IRQ in CPU */
     CPU_INT_EN |= USB_MASK;
+#endif
 
     /* go go go */
     REG_USBCMD |= USBCMD_RUN;
 
-
     logf("usb_drv_init() finished");
     logf("usb id %x", REG_ID);
     logf("usb dciversion %x", REG_DCIVERSION);
@@ -411,10 +427,18 @@
     REG_USBCMD |= USBCMD_CTRL_RESET;
     */
 
+#if CONFIG_CPU == IMX31L
+    avic_disable_int(USB_OTG);
+#endif
+
     cancel_cpu_boost();
 }
 
+#if CONFIG_CPU == IMX31L
+void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void)
+#else
 void usb_drv_int(void)
+#endif
 {
     unsigned int status = REG_USBSTS;
 
Index: firmware/target/arm/imx31/gigabeat-s/usb-target.h
===================================================================
--- firmware/target/arm/imx31/gigabeat-s/usb-target.h	(revision 17109)
+++ firmware/target/arm/imx31/gigabeat-s/usb-target.h	(working copy)
@@ -19,6 +19,7 @@
 #ifndef USB_TARGET_H
 #define USB_TARGET_H
 
+void usb_set_status(bool plugged);
 bool usb_init_device(void);
 int usb_detect(void);
 void usb_enable(bool on);
Index: firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
===================================================================
--- firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c	(revision 17109)
+++ firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c	(working copy)
@@ -27,6 +27,7 @@
 #include "power-imx31.h"
 #include "button-target.h"
 #include "adc-target.h"
+#include "usb-target.h"
 
 /* This is all based on communicating with the MC13783 PMU which is on 
  * CSPI2 with the chip select at 0. The LCD controller resides on
@@ -67,6 +68,7 @@
 
     /* Check initial states for events with a sense bit */
     value = mc13783_read(MC13783_INTERRUPT_SENSE0);
+    usb_set_status(value & MC13783_USB4V4);
     set_charger_inserted(value & MC13783_CHGDET);
 
     value = mc13783_read(MC13783_INTERRUPT_SENSE1);
@@ -98,12 +100,15 @@
 
             /* Handle interrupts that have a sense bit that needs to
              * be checked */
-            if (pending[0] & MC13783_CHGDET)
+            if (pending[0] & (MC13783_CHGDET | MC13783_USB4V4))
             {
                 value = mc13783_read(MC13783_INTERRUPT_SENSE0);
 
                 if (pending[0] & MC13783_CHGDET)
                     set_charger_inserted(value & MC13783_CHGDET);
+
+                if (pending[0] & MC13783_USB4V4)
+                    usb_set_status(value & MC13783_USB4V4);
             }
         }
 
Index: firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
===================================================================
--- firmware/target/arm/imx31/gigabeat-s/usb-imx31.c	(revision 17109)
+++ firmware/target/arm/imx31/gigabeat-s/usb-imx31.c	(working copy)
@@ -22,17 +22,39 @@
 #include "kernel.h"
 #include "ata.h"
 #include "usb.h"
+#include "usb_core.h"
+#include "clkctl-imx31.h"
+#include "mc13783.h"
 
-inline int usb_detect(void)
+static int usb_status = USB_EXTRACTED;
+
+void usb_set_status(bool plugged)
 {
-    return USB_EXTRACTED;
+    usb_status = plugged ? USB_INSERTED : USB_EXTRACTED;
 }
 
+int usb_detect(void)
+{
+    return usb_status;
+}
+
 void usb_init_device(void)
 {
+    mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_USB4V4);
 }
 
 void usb_enable(bool on)
 {
-    (void)on;
+    if (on)
+    {
+        GPIO1_DR &= ~(1 << 30); /* Select ISP1504 */
+        imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_ON_ALL);
+        usb_core_init();
+    }
+    else
+    {
+        usb_core_exit();
+        imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_OFF);
+        GPIO1_DR |= (1 << 30); /* Deselect ISP1504 */
+    }
 }
Index: firmware/target/arm/imx31/debug-imx31.c
===================================================================
--- firmware/target/arm/imx31/debug-imx31.c	(revision 17109)
+++ firmware/target/arm/imx31/debug-imx31.c	(working copy)
@@ -138,6 +138,17 @@
             lcd_puts(0, line++, buf);
         }
 
+        snprintf(buf, sizeof(buf), "%08lX",
+                 SW_MUX_CTL_USB_PWR_USB_OC_USB_BYP_USBOTG_CLK);
+        lcd_puts(0, line++, buf);
+
+        snprintf(buf, sizeof(buf), "%08lX",
+                 SW_MUX_CTL_CSI_D14_CSI_D15_CSI_MCLK_CSI_VSYNC);
+        lcd_puts(0, line++, buf);
+
+        snprintf(buf, sizeof(buf), "%08lX", IOMUXC_GPR);
+        lcd_puts(0, line++, buf);
+
         lcd_update();
         if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL))
             return false;
