Merge branch 'master' of git://git.denx.de/u-boot-mmc
diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c
index eaf09d1..81477aa 100644
--- a/arch/arm/cpu/armv7/am33xx/board.c
+++ b/arch/arm/cpu/armv7/am33xx/board.c
@@ -285,14 +285,6 @@
 #ifdef CONFIG_NOR_BOOT
 	enable_norboot_pin_mux();
 #endif
-	/*
-	 * Save the boot parameters passed from romcode.
-	 * We cannot delay the saving further than this,
-	 * to prevent overwrites.
-	 */
-#ifdef CONFIG_SPL_BUILD
-	save_omap_boot_params();
-#endif
 	watchdog_disable();
 	set_uart_mux_conf();
 	setup_clocks_for_console();
@@ -301,9 +293,6 @@
 	gd->baudrate = CONFIG_BAUDRATE;
 	serial_init();
 	gd->have_console = 1;
-#elif defined(CONFIG_SPL_BUILD)
-	gd = &gdata;
-	preloader_console_init();
 #endif
 #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
 	/* Enable RTC32K clock */
diff --git a/arch/arm/cpu/armv7/omap-common/boot-common.c b/arch/arm/cpu/armv7/omap-common/boot-common.c
index 00a1082..17500f2 100644
--- a/arch/arm/cpu/armv7/omap-common/boot-common.c
+++ b/arch/arm/cpu/armv7/omap-common/boot-common.c
@@ -106,6 +106,16 @@
 
 void spl_board_init(void)
 {
+	/*
+	 * Save the boot parameters passed from romcode.
+	 * We cannot delay the saving further than this,
+	 * to prevent overwrites.
+	 */
+	save_omap_boot_params();
+
+	/* Prepare console output */
+	preloader_console_init();
+
 #ifdef CONFIG_SPL_NAND_SUPPORT
 	gpmc_init();
 #endif
diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
index dd52e93..cb35c19 100644
--- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c
+++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
@@ -111,14 +111,6 @@
  */
 void s_init(void)
 {
-	/*
-	 * Save the boot parameters passed from romcode.
-	 * We cannot delay the saving further than this,
-	 * to prevent overwrites.
-	 */
-#ifdef CONFIG_SPL_BUILD
-	save_omap_boot_params();
-#endif
 	init_omap_revision();
 	hw_data_init();
 
@@ -133,9 +125,6 @@
 	srcomp_enable();
 	setup_clocks_for_console();
 
-	gd = &gdata;
-
-	preloader_console_init();
 	do_io_settings();
 #endif
 	prcm_init();
diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index 53a9e5d..90d6ae7 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -119,6 +119,7 @@
 
 void spl_board_init(void)
 {
+	preloader_console_init();
 #if defined(CONFIG_SPL_NAND_SUPPORT) || defined(CONFIG_SPL_ONENAND_SUPPORT)
 	gpmc_init();
 #endif
@@ -264,14 +265,6 @@
 	ehci_clocks_enable();
 #endif
 
-#ifdef CONFIG_SPL_BUILD
-	gd = &gdata;
-
-	preloader_console_init();
-
-	timer_init();
-#endif
-
 	if (!in_sdram)
 		mem_init();
 }
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index bc98c56..f4a580a 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -46,9 +46,8 @@
 {
 	return MMCSD_MODE_RAW;
 }
-#endif
 
-int gpio_init(void)
+static int gpio_init(void)
 {
 #if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
@@ -86,6 +85,42 @@
 	return 0;
 }
 
+void board_init_f(ulong dummy)
+{
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+	/* Magic (undocmented) value taken from boot0, without this DRAM
+	 * access gets messed up (seems cache related) */
+	setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
+#endif
+#if !defined CONFIG_SPL_BUILD && (defined CONFIG_MACH_SUN7I || \
+		defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
+	/* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
+	asm volatile(
+		"mrc p15, 0, r0, c1, c0, 1\n"
+		"orr r0, r0, #1 << 6\n"
+		"mcr p15, 0, r0, c1, c0, 1\n");
+#endif
+
+	clock_init();
+	timer_init();
+	gpio_init();
+	i2c_init_board();
+
+	preloader_console_init();
+
+#ifdef CONFIG_SPL_I2C_SUPPORT
+	/* Needed early by sunxi_board_init if PMU is enabled */
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#endif
+	sunxi_board_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	board_init_r(NULL, 0);
+}
+#endif
+
 void reset_cpu(ulong addr)
 {
 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
@@ -111,41 +146,6 @@
 #endif
 }
 
-/* do some early init */
-void s_init(void)
-{
-#if defined CONFIG_SPL_BUILD && \
-		(defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
-	/* Magic (undocmented) value taken from boot0, without this DRAM
-	 * access gets messed up (seems cache related) */
-	setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
-#endif
-#if !defined CONFIG_SPL_BUILD && (defined CONFIG_MACH_SUN7I || \
-		defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
-	/* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
-	asm volatile(
-		"mrc p15, 0, r0, c1, c0, 1\n"
-		"orr r0, r0, #1 << 6\n"
-		"mcr p15, 0, r0, c1, c0, 1\n");
-#endif
-
-	clock_init();
-	timer_init();
-	gpio_init();
-	i2c_init_board();
-
-#ifdef CONFIG_SPL_BUILD
-	gd = &gdata;
-	preloader_console_init();
-
-#ifdef CONFIG_SPL_I2C_SUPPORT
-	/* Needed early by sunxi_board_init if PMU is enabled */
-	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
-#endif
-	sunxi_board_init();
-#endif
-}
-
 #ifndef CONFIG_SYS_DCACHE_OFF
 void enable_caches(void)
 {
diff --git a/arch/arm/cpu/armv7/zynq/spl.c b/arch/arm/cpu/armv7/zynq/spl.c
index 31627f9..0936bdd 100644
--- a/arch/arm/cpu/armv7/zynq/spl.c
+++ b/arch/arm/cpu/armv7/zynq/spl.c
@@ -20,9 +20,6 @@
 	/* Clear the BSS. */
 	memset(__bss_start, 0, __bss_end - __bss_start);
 
-	/* Set global data pointer. */
-	gd = &gdata;
-
 	preloader_console_init();
 	arch_cpu_init();
 	board_init_r(NULL, 0);
diff --git a/arch/arm/lib/spl.c b/arch/arm/lib/spl.c
index dfcc596..c41850a 100644
--- a/arch/arm/lib/spl.c
+++ b/arch/arm/lib/spl.c
@@ -15,6 +15,11 @@
 
 /* Pointer to as well as the global data structure for SPL */
 DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * WARNING: This is going away very soon. Don't use it and don't submit
+ * pafches that rely on it. The global_data area is set up in crt0.S.
+ */
 gd_t gdata __attribute__ ((section(".data")));
 
 /*
@@ -28,7 +33,7 @@
 	/* Clear the BSS. */
 	memset(__bss_start, 0, __bss_end - __bss_start);
 
-	/* Set global data pointer. */
+	/* TODO: Remove settings of the global data pointer here */
 	gd = &gdata;
 
 	board_init_r(NULL, 0);
diff --git a/board/compulab/cm_fx6/spl.c b/board/compulab/cm_fx6/spl.c
index 6fe937b..5b4b76f 100644
--- a/board/compulab/cm_fx6/spl.c
+++ b/board/compulab/cm_fx6/spl.c
@@ -313,7 +313,6 @@
 {
 	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 
-	gd = &gdata;
 	/*
 	 * We don't use DMA in SPL, but we do need it in U-Boot. U-Boot
 	 * initializes DMA very early (before all board code), so the only
diff --git a/board/freescale/ls1021aqds/ls1021aqds.c b/board/freescale/ls1021aqds/ls1021aqds.c
index f08e54f..152da2d 100644
--- a/board/freescale/ls1021aqds/ls1021aqds.c
+++ b/board/freescale/ls1021aqds/ls1021aqds.c
@@ -219,9 +219,6 @@
 		 pinctl);
 #endif
 
-	/* Set global data pointer */
-	gd = &gdata;
-
 	/* Clear the BSS */
 	memset(__bss_start, 0, __bss_end - __bss_start);
 
diff --git a/board/freescale/ls1021atwr/ls1021atwr.c b/board/freescale/ls1021atwr/ls1021atwr.c
index 8ab229d..027b67e 100644
--- a/board/freescale/ls1021atwr/ls1021atwr.c
+++ b/board/freescale/ls1021atwr/ls1021atwr.c
@@ -287,9 +287,6 @@
 #ifdef CONFIG_SPL_BUILD
 void board_init_f(ulong dummy)
 {
-	/* Set global data pointer */
-	gd = &gdata;
-
 	/* Clear the BSS */
 	memset(__bss_start, 0, __bss_end - __bss_start);
 
diff --git a/board/freescale/mpc837xerdb/MAINTAINERS b/board/freescale/mpc837xerdb/MAINTAINERS
index 8592a2c..81b4eed 100644
--- a/board/freescale/mpc837xerdb/MAINTAINERS
+++ b/board/freescale/mpc837xerdb/MAINTAINERS
@@ -1,6 +1,6 @@
 MPC837XERDB BOARD
-#M:	Joe D'Abbraccio <ljd015@freescale.com>
-S:	Orphan (since 2014-06)
+M:	Sinan Akman <sinan@writeme.com>
+S:	Maintained
 F:	board/freescale/mpc837xerdb/
 F:	include/configs/MPC837XERDB.h
 F:	configs/MPC837XERDB_defconfig
diff --git a/board/woodburn/woodburn.c b/board/woodburn/woodburn.c
index 2744514..3da61a4 100644
--- a/board/woodburn/woodburn.c
+++ b/board/woodburn/woodburn.c
@@ -137,9 +137,6 @@
 	/* Clear the BSS. */
 	memset(__bss_start, 0, __bss_end - __bss_start);
 
-	/* Set global data pointer. */
-	gd = &gdata;
-
 	preloader_console_init();
 	timer_init();
 
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index c192498..27813f0 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -441,6 +441,26 @@
 	return 0;
 }
 
+static void do_usb_start(void)
+{
+	bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
+
+	if (usb_init() < 0)
+		return;
+
+#ifdef CONFIG_USB_STORAGE
+	/* try to recognize storage devices immediately */
+	usb_stor_curr_dev = usb_stor_scan(1);
+#endif
+#ifdef CONFIG_USB_HOST_ETHER
+	/* try to recognize ethernet devices immediately */
+	usb_ether_curr_dev = usb_host_eth_scan(1);
+#endif
+#ifdef CONFIG_USB_KEYBOARD
+	drv_usb_kbd_init();
+#endif
+}
+
 /******************************************************************************
  * usb command intepreter
  */
@@ -457,26 +477,20 @@
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	if ((strncmp(argv[1], "reset", 5) == 0) ||
-		 (strncmp(argv[1], "start", 5) == 0)) {
-		bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
+	if (strncmp(argv[1], "start", 5) == 0) {
+		if (usb_started)
+			return 0; /* Already started */
+		printf("starting USB...\n");
+		do_usb_start();
+		return 0;
+	}
+
+	if (strncmp(argv[1], "reset", 5) == 0) {
+		printf("resetting USB...\n");
 		if (do_usb_stop_keyboard(1) != 0)
 			return 1;
 		usb_stop();
-		printf("(Re)start USB...\n");
-		if (usb_init() >= 0) {
-#ifdef CONFIG_USB_STORAGE
-			/* try to recognize storage devices immediately */
-			usb_stor_curr_dev = usb_stor_scan(1);
-#endif
-#ifdef CONFIG_USB_HOST_ETHER
-			/* try to recognize ethernet devices immediately */
-			usb_ether_curr_dev = usb_host_eth_scan(1);
-#endif
-#ifdef CONFIG_USB_KEYBOARD
-			drv_usb_kbd_init();
-#endif
-		}
+		do_usb_start();
 		return 0;
 	}
 	if (strncmp(argv[1], "stop", 4) == 0) {
diff --git a/common/usb.c b/common/usb.c
index 736cd9f..32e15cd 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -59,6 +59,7 @@
 	void *ctrl;
 	struct usb_device *dev;
 	int i, start_index = 0;
+	int controllers_initialized = 0;
 	int ret;
 
 	dev_index = 0;
@@ -78,6 +79,7 @@
 		ret = usb_lowlevel_init(i, USB_INIT_HOST, &ctrl);
 		if (ret == -ENODEV) {	/* No such device. */
 			puts("Port not available.\n");
+			controllers_initialized++;
 			continue;
 		}
 
@@ -89,6 +91,7 @@
 		 * lowlevel init is OK, now scan the bus for devices
 		 * i.e. search HUBs and configure them
 		 */
+		controllers_initialized++;
 		start_index = dev_index;
 		printf("scanning bus %d for devices... ", i);
 		dev = usb_alloc_new_device(ctrl);
@@ -110,12 +113,10 @@
 
 	debug("scan end\n");
 	/* if we were not able to find at least one working bus, bail out */
-	if (!usb_started) {
+	if (controllers_initialized == 0)
 		puts("USB error: all controllers failed lowlevel init\n");
-		return -1;
-	}
 
-	return 0;
+	return usb_started ? 0 : -1;
 }
 
 /******************************************************************************
@@ -969,6 +970,8 @@
 			printf("\n     Couldn't reset port %i\n", dev->portnr);
 			return 1;
 		}
+	} else {
+		usb_reset_root_port();
 	}
 #endif
 
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index bc7145e..ecc3085 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -332,7 +332,8 @@
 		/* We've consumed all queued int packets, create new */
 		destroy_int_queue(dev, data->intq);
 		data->intq = create_int_queue(dev, data->intpipe, 1,
-				      USB_KBD_BOOT_REPORT_SIZE, data->new);
+				      USB_KBD_BOOT_REPORT_SIZE, data->new,
+				      data->intinterval);
 	}
 #endif
 }
@@ -453,7 +454,8 @@
 	debug("USB KBD: enable interrupt pipe...\n");
 #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
 	data->intq = create_int_queue(dev, data->intpipe, 1,
-				      USB_KBD_BOOT_REPORT_SIZE, data->new);
+				      USB_KBD_BOOT_REPORT_SIZE, data->new,
+				      data->intinterval);
 	if (!data->intq) {
 #else
 	if (usb_submit_int_msg(dev, data->intpipe, data->new, data->intpktsize,
@@ -542,6 +544,10 @@
 		data = usb_kbd_dev->privptr;
 		if (stdio_deregister_dev(dev, force) != 0)
 			return 1;
+#ifdef CONFIG_CONSOLE_MUX
+		if (iomux_doenv(stdin, getenv("stdin")) != 0)
+			return 1;
+#endif
 #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
 		destroy_int_queue(usb_kbd_dev, data->intq);
 #endif
diff --git a/drivers/usb/eth/asix88179.c b/drivers/usb/eth/asix88179.c
index b8ca720..0ef85db 100644
--- a/drivers/usb/eth/asix88179.c
+++ b/drivers/usb/eth/asix88179.c
@@ -271,6 +271,19 @@
 	return 0;
 }
 
+static int asix_write_mac(struct eth_device *eth)
+{
+	struct ueth_data *dev = (struct ueth_data *)eth->priv;
+	int ret;
+
+	ret = asix_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
+				 ETH_ALEN, eth->enetaddr);
+	if (ret < 0)
+		debug("Failed to set MAC address: %02x\n", ret);
+
+	return ret;
+}
+
 static int asix_basic_reset(struct ueth_data *dev)
 {
 	struct asix_private *dev_priv = (struct asix_private *)dev->dev_priv;
@@ -686,6 +699,7 @@
 	eth->send = asix_send;
 	eth->recv = asix_recv;
 	eth->halt = asix_halt;
+	eth->write_hwaddr = asix_write_mac;
 	eth->priv = ss;
 
 	if (asix_basic_reset(ss))
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index a4c5606..98c2da6 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -761,6 +761,14 @@
 			if (value >= 0)
 				value = min(w_length, (u16) value);
 			break;
+		case USB_DT_BOS:
+			/*
+			 * The USB compliance test (USB 2.0 Command Verifier)
+			 * issues this request. We should not run into the
+			 * default path here. But return for now until
+			 * the superspeed support is added.
+			 */
+			break;
 		default:
 			goto unknown;
 		}
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index ead71eb..77a1567 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -780,6 +780,13 @@
 	return 0;
 }
 
+static int __dfu_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+
+	return f_dfu->altsetting;
+}
+
 /* TODO: is this really what we need here? */
 static void dfu_disable(struct usb_function *f)
 {
@@ -806,6 +813,7 @@
 	f_dfu->usb_function.bind = dfu_bind;
 	f_dfu->usb_function.unbind = dfu_unbind;
 	f_dfu->usb_function.set_alt = dfu_set_alt;
+	f_dfu->usb_function.get_alt = __dfu_get_alt;
 	f_dfu->usb_function.disable = dfu_disable;
 	f_dfu->usb_function.strings = dfu_generic_strings;
 	f_dfu->usb_function.setup = dfu_handle;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 8945c5b..d4460b2 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -1950,11 +1950,11 @@
 	dev->watchdog.period = 5000 * CONFIG_SYS_HZ / 1000000; /* 5 ms */
 	dev->watchdog.function = udc_watchdog;
 
+	dev->mach = &mach_info;
+
 	udc_disable(dev);
 	udc_reinit(dev);
 
-	dev->mach = &mach_info;
-
 	dev->gadget.name = "pxa2xx_udc";
 	retval = driver->bind(&dev->gadget);
 	if (retval) {
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index bc76066..f1fb190 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1148,7 +1148,7 @@
 
 struct int_queue *
 create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
-		 int elementsize, void *buffer)
+		 int elementsize, void *buffer, int interval)
 {
 	struct ehci_ctrl *ctrl = dev->controller;
 	struct int_queue *result = NULL;
@@ -1398,7 +1398,7 @@
 	debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
 	      dev, pipe, buffer, length, interval);
 
-	queue = create_int_queue(dev, pipe, 1, length, buffer);
+	queue = create_int_queue(dev, pipe, 1, length, buffer, interval);
 	if (!queue)
 		return -1;
 
diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile
index 3facf0f..9edeece 100644
--- a/drivers/usb/musb-new/Makefile
+++ b/drivers/usb/musb-new/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o
 obj-$(CONFIG_USB_MUSB_AM35X) += am35x.o
 obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o
+obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
 
 ccflags-y := $(call cc-option,-Wno-unused-variable) \
 		$(call cc-option,-Wno-unused-but-set-variable) \
diff --git a/drivers/usb/musb-new/musb_host.c b/drivers/usb/musb-new/musb_host.c
index bbcee88..437309c 100644
--- a/drivers/usb/musb-new/musb_host.c
+++ b/drivers/usb/musb-new/musb_host.c
@@ -2130,8 +2130,6 @@
 	return ret;
 }
 
-
-#ifndef __UBOOT__
 /*
  * abort a transfer that's at the head of a hardware queue.
  * called with controller locked, irqs blocked
@@ -2195,7 +2193,14 @@
 	return status;
 }
 
-static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+#ifndef __UBOOT__
+static int musb_urb_dequeue(
+#else
+int musb_urb_dequeue(
+#endif
+	struct usb_hcd *hcd,
+	struct urb *urb,
+	int status)
 {
 	struct musb		*musb = hcd_to_musb(hcd);
 	struct musb_qh		*qh;
@@ -2253,6 +2258,7 @@
 	return ret;
 }
 
+#ifndef __UBOOT__
 /* disable an endpoint */
 static void
 musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
diff --git a/drivers/usb/musb-new/musb_host.h b/drivers/usb/musb-new/musb_host.h
index ebebe0c..546b4a2 100644
--- a/drivers/usb/musb-new/musb_host.h
+++ b/drivers/usb/musb-new/musb_host.h
@@ -110,5 +110,6 @@
 
 #ifdef __UBOOT__
 int musb_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
+int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
 #endif
 #endif				/* _MUSB_HOST_H */
diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h
index 03f2655..27e4ed4 100644
--- a/drivers/usb/musb-new/musb_regs.h
+++ b/drivers/usb/musb-new/musb_regs.h
@@ -216,6 +216,9 @@
 
 #ifndef CONFIG_BLACKFIN
 
+/* SUNXI has different reg addresses, but identical r/w functions */
+#ifndef CONFIG_ARCH_SUNXI 
+
 /*
  * Common USB registers
  */
@@ -318,6 +321,85 @@
 #define MUSB_BUSCTL_OFFSET(_epnum, _offset) \
 	(0x80 + (8*(_epnum)) + (_offset))
 
+#else /* CONFIG_ARCH_SUNXI */
+
+/*
+ * Common USB registers
+ */
+
+#define MUSB_FADDR		0x0098
+#define MUSB_POWER		0x0040
+
+#define MUSB_INTRTX		0x0044
+#define MUSB_INTRRX		0x0046
+#define MUSB_INTRTXE		0x0048
+#define MUSB_INTRRXE		0x004A
+#define MUSB_INTRUSB		0x004C
+#define MUSB_INTRUSBE		0x0050
+#define MUSB_FRAME		0x0054
+#define MUSB_INDEX		0x0042
+#define MUSB_TESTMODE		0x007C
+
+/* Get offset for a given FIFO from musb->mregs */
+#define MUSB_FIFO_OFFSET(epnum)	(0x00 + ((epnum) * 4))
+
+/*
+ * Additional Control Registers
+ */
+
+#define MUSB_DEVCTL		0x0041
+
+/* These are always controlled through the INDEX register */
+#define MUSB_TXFIFOSZ		0x0090
+#define MUSB_RXFIFOSZ		0x0094
+#define MUSB_TXFIFOADD		0x0092
+#define MUSB_RXFIFOADD		0x0096
+
+#define MUSB_EPINFO		0x0078
+#define MUSB_RAMINFO		0x0079
+#define MUSB_LINKINFO		0x007A
+#define MUSB_VPLEN		0x007B
+#define MUSB_HS_EOF1		0x007C
+#define MUSB_FS_EOF1		0x007D
+#define MUSB_LS_EOF1		0x007E
+
+/* Offsets to endpoint registers */
+#define MUSB_TXMAXP		0x0080
+#define MUSB_TXCSR		0x0082
+#define MUSB_CSR0		0x0082
+#define MUSB_RXMAXP		0x0084
+#define MUSB_RXCSR		0x0086
+#define MUSB_RXCOUNT		0x0088
+#define MUSB_COUNT0		0x0088
+#define MUSB_TXTYPE		0x008C
+#define MUSB_TYPE0		0x008C
+#define MUSB_TXINTERVAL		0x008D
+#define MUSB_NAKLIMIT0		0x008D
+#define MUSB_RXTYPE		0x008E
+#define MUSB_RXINTERVAL		0x008F
+
+#define MUSB_CONFIGDATA		0x00b0 /* musb_read_configdata adds 0x10 ! */
+#define MUSB_FIFOSIZE		0x0090
+
+/* Offsets to endpoint registers in indexed model (using INDEX register) */
+#define MUSB_INDEXED_OFFSET(_epnum, _offset) (_offset)
+
+#define MUSB_TXCSR_MODE		0x2000
+
+/* "bus control"/target registers, for host side multipoint (external hubs) */
+#define MUSB_TXFUNCADDR		0x0098
+#define MUSB_TXHUBADDR		0x009A
+#define MUSB_TXHUBPORT		0x009B
+
+#define MUSB_RXFUNCADDR		0x009C
+#define MUSB_RXHUBADDR		0x009E
+#define MUSB_RXHUBPORT		0x009F
+
+/* Endpoint is selected with MUSB_INDEX. */
+#define MUSB_BUSCTL_OFFSET(_epnum, _offset) (_offset)
+
+#endif /* CONFIG_ARCH_SUNXI */
+
 static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
 {
 	musb_writeb(mbase, MUSB_TXFIFOSZ, c_size);
@@ -340,7 +422,9 @@
 
 static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val)
 {
+#ifndef CONFIG_ARCH_SUNXI /* No ulpi on sunxi */
 	musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val);
+#endif
 }
 
 static inline u8 musb_read_txfifosz(void __iomem *mbase)
@@ -365,7 +449,11 @@
 
 static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
 {
+#ifdef CONFIG_ARCH_SUNXI /* No ulpi on sunxi */
+	return 0;
+#else
 	return musb_readb(mbase, MUSB_ULPI_BUSCONTROL);
+#endif
 }
 
 static inline u8 musb_read_configdata(void __iomem *mbase)
@@ -376,7 +464,11 @@
 
 static inline u16 musb_read_hwvers(void __iomem *mbase)
 {
+#ifdef CONFIG_ARCH_SUNXI
+	return 0; /* Unknown version */
+#else
 	return musb_readw(mbase, MUSB_HWVERS);
+#endif
 }
 
 static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase)
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index 2676f09..6e58ddf 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -12,6 +12,11 @@
 #include "musb_gadget.h"
 
 #ifdef CONFIG_MUSB_HOST
+struct int_queue {
+	struct usb_host_endpoint hep;
+	struct urb urb;
+};
+
 static struct musb *host;
 static struct usb_hcd hcd;
 static enum usb_device_speed host_speed;
@@ -25,45 +30,42 @@
 static struct usb_host_endpoint hep;
 static struct urb urb;
 
-static struct urb *construct_urb(struct usb_device *dev, int endpoint_type,
-				unsigned long pipe, void *buffer, int len,
-				struct devrequest *setup, int interval)
+static void construct_urb(struct urb *urb, struct usb_host_endpoint *hep,
+			  struct usb_device *dev, int endpoint_type,
+			  unsigned long pipe, void *buffer, int len,
+			  struct devrequest *setup, int interval)
 {
 	int epnum = usb_pipeendpoint(pipe);
 	int is_in = usb_pipein(pipe);
 
-	memset(&urb, 0, sizeof(struct urb));
-	memset(&hep, 0, sizeof(struct usb_host_endpoint));
-	INIT_LIST_HEAD(&hep.urb_list);
-	INIT_LIST_HEAD(&urb.urb_list);
-	urb.ep = &hep;
-	urb.complete = musb_host_complete_urb;
-	urb.status = -EINPROGRESS;
-	urb.dev = dev;
-	urb.pipe = pipe;
-	urb.transfer_buffer = buffer;
-	urb.transfer_dma = (unsigned long)buffer;
-	urb.transfer_buffer_length = len;
-	urb.setup_packet = (unsigned char *)setup;
+	memset(urb, 0, sizeof(struct urb));
+	memset(hep, 0, sizeof(struct usb_host_endpoint));
+	INIT_LIST_HEAD(&hep->urb_list);
+	INIT_LIST_HEAD(&urb->urb_list);
+	urb->ep = hep;
+	urb->complete = musb_host_complete_urb;
+	urb->status = -EINPROGRESS;
+	urb->dev = dev;
+	urb->pipe = pipe;
+	urb->transfer_buffer = buffer;
+	urb->transfer_dma = (unsigned long)buffer;
+	urb->transfer_buffer_length = len;
+	urb->setup_packet = (unsigned char *)setup;
 
-	urb.ep->desc.wMaxPacketSize =
+	urb->ep->desc.wMaxPacketSize =
 		__cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] :
 				dev->epmaxpacketout[epnum]);
-	urb.ep->desc.bmAttributes = endpoint_type;
-	urb.ep->desc.bEndpointAddress =
+	urb->ep->desc.bmAttributes = endpoint_type;
+	urb->ep->desc.bEndpointAddress =
 		(is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum;
-	urb.ep->desc.bInterval = interval;
-
-	return &urb;
+	urb->ep->desc.bInterval = interval;
 }
 
-#define MUSB_HOST_TIMEOUT	0x3ffffff
-
 static int submit_urb(struct usb_hcd *hcd, struct urb *urb)
 {
 	struct musb *host = hcd->hcd_priv;
 	int ret;
-	int timeout;
+	unsigned long timeout;
 
 	ret = musb_urb_enqueue(hcd, urb, 0);
 	if (ret < 0) {
@@ -71,12 +73,16 @@
 		return ret;
 	}
 
-	timeout = MUSB_HOST_TIMEOUT;
+	timeout = get_timer(0) + USB_TIMEOUT_MS(urb->pipe);
 	do {
 		if (ctrlc())
 			return -EIO;
 		host->isr(0, host);
-	} while ((urb->dev->status & USB_ST_NOT_PROC) && --timeout);
+	} while (urb->status == -EINPROGRESS &&
+		 get_timer(0) < timeout);
+
+	if (urb->status == -EINPROGRESS)
+		musb_urb_dequeue(hcd, urb, -ETIME);
 
 	return urb->status;
 }
@@ -84,38 +90,117 @@
 int submit_control_msg(struct usb_device *dev, unsigned long pipe,
 			void *buffer, int len, struct devrequest *setup)
 {
-	struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_CONTROL, pipe,
-					buffer, len, setup, 0);
+	construct_urb(&urb, &hep, dev, USB_ENDPOINT_XFER_CONTROL, pipe,
+		      buffer, len, setup, 0);
 
 	/* Fix speed for non hub-attached devices */
 	if (!dev->parent)
 		dev->speed = host_speed;
 
-	return submit_urb(&hcd, urb);
+	return submit_urb(&hcd, &urb);
 }
 
 
 int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
 					void *buffer, int len)
 {
-	struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_BULK, pipe,
-					buffer, len, NULL, 0);
-	return submit_urb(&hcd, urb);
+	construct_urb(&urb, &hep, dev, USB_ENDPOINT_XFER_BULK, pipe,
+		      buffer, len, NULL, 0);
+	return submit_urb(&hcd, &urb);
 }
 
 int submit_int_msg(struct usb_device *dev, unsigned long pipe,
 				void *buffer, int len, int interval)
 {
-	struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_INT, pipe,
-					buffer, len, NULL, interval);
-	return submit_urb(&hcd, urb);
+	construct_urb(&urb, &hep, dev, USB_ENDPOINT_XFER_INT, pipe,
+		      buffer, len, NULL, interval);
+	return submit_urb(&hcd, &urb);
+}
+
+struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
+	int queuesize, int elementsize, void *buffer, int interval)
+{
+	struct int_queue *queue;
+	int ret, index = usb_pipein(pipe) * 16 + usb_pipeendpoint(pipe);
+
+	if (queuesize != 1) {
+		printf("ERROR musb int-queues only support queuesize 1\n");
+		return NULL;
+	}
+
+	if (dev->int_pending & (1 << index)) {
+		printf("ERROR int-urb is already pending on pipe %lx\n", pipe);
+		return NULL;
+	}
+
+	queue = malloc(sizeof(*queue));
+	if (!queue)
+		return NULL;
+
+	construct_urb(&queue->urb, &queue->hep, dev, USB_ENDPOINT_XFER_INT,
+		      pipe, buffer, elementsize, NULL, interval);
+
+	ret = musb_urb_enqueue(&hcd, &queue->urb, 0);
+	if (ret < 0) {
+		printf("Failed to enqueue URB to controller\n");
+		free(queue);
+		return NULL;
+	}
+
+	dev->int_pending |= 1 << index;
+	return queue;
+}
+
+int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+	int index = usb_pipein(queue->urb.pipe) * 16 + 
+		    usb_pipeendpoint(queue->urb.pipe);
+
+	if (queue->urb.status == -EINPROGRESS)
+		musb_urb_dequeue(&hcd, &queue->urb, -ETIME);
+
+	dev->int_pending &= ~(1 << index);
+	free(queue);
+	return 0;
+}
+
+void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+	if (queue->urb.status != -EINPROGRESS)
+		return NULL; /* URB has already completed in a prev. poll */
+
+	host->isr(0, host);
+
+	if (queue->urb.status != -EINPROGRESS)
+		return queue->urb.transfer_buffer; /* Done */
+
+	return NULL; /* URB still pending */
+}
+
+void usb_reset_root_port(void)
+{
+	void *mbase = host->mregs;
+	u8 power;
+
+	power = musb_readb(mbase, MUSB_POWER);
+	power &= 0xf0;
+	musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
+	mdelay(50);
+	power = musb_readb(mbase, MUSB_POWER);
+	musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
+	host->isr(0, host);
+	host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
+			USB_SPEED_HIGH :
+			(musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
+			USB_SPEED_FULL : USB_SPEED_LOW;
+	mdelay((host_speed == USB_SPEED_LOW) ? 200 : 50);
 }
 
 int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 {
-	u8 power;
 	void *mbase;
-	int timeout = MUSB_HOST_TIMEOUT;
+	/* USB spec says it may take up to 1 second for a device to connect */
+	unsigned long timeout = get_timer(0) + 1000;
 
 	if (!host) {
 		printf("MUSB host is not registered\n");
@@ -127,20 +212,11 @@
 	do {
 		if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
 			break;
-	} while (--timeout);
-	if (!timeout)
+	} while (get_timer(0) < timeout);
+	if (get_timer(0) >= timeout)
 		return -ENODEV;
 
-	power = musb_readb(mbase, MUSB_POWER);
-	musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
-	udelay(30000);
-	power = musb_readb(mbase, MUSB_POWER);
-	musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
-	host->isr(0, host);
-	host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
-			USB_SPEED_HIGH :
-			(musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
-			USB_SPEED_FULL : USB_SPEED_LOW;
+	usb_reset_root_port();
 	host->is_active = 1;
 	hcd.hcd_priv = host;
 
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
new file mode 100644
index 0000000..778916d
--- /dev/null
+++ b/drivers/usb/musb-new/sunxi.c
@@ -0,0 +1,279 @@
+/*
+ * Allwinner SUNXI "glue layer"
+ *
+ * Copyright © 2015 Hans de Goede <hdegoede@redhat.com>
+ * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * Based on the sw_usb "Allwinner OTG Dual Role Controller" code.
+ *  Copyright 2007-2012 (C) Allwinner Technology Co., Ltd.
+ *  javen <javen@allwinnertech.com>
+ *
+ * Based on the DA8xx "glue layer" code.
+ *  Copyright (c) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *  Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ */
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/usbc.h>
+#include "linux-compat.h"
+#include "musb_core.h"
+
+/******************************************************************************
+ ******************************************************************************
+ * From the Allwinner driver
+ ******************************************************************************
+ ******************************************************************************/
+
+/******************************************************************************
+ * From include/sunxi_usb_bsp.h
+ ******************************************************************************/
+
+/* reg offsets */
+#define  USBC_REG_o_ISCR	0x0400
+#define  USBC_REG_o_PHYCTL	0x0404
+#define  USBC_REG_o_PHYBIST	0x0408
+#define  USBC_REG_o_PHYTUNE	0x040c
+
+#define  USBC_REG_o_VEND0	0x0043
+
+/* Interface Status and Control */
+#define  USBC_BP_ISCR_VBUS_VALID_FROM_DATA	30
+#define  USBC_BP_ISCR_VBUS_VALID_FROM_VBUS	29
+#define  USBC_BP_ISCR_EXT_ID_STATUS		28
+#define  USBC_BP_ISCR_EXT_DM_STATUS		27
+#define  USBC_BP_ISCR_EXT_DP_STATUS		26
+#define  USBC_BP_ISCR_MERGED_VBUS_STATUS	25
+#define  USBC_BP_ISCR_MERGED_ID_STATUS		24
+
+#define  USBC_BP_ISCR_ID_PULLUP_EN		17
+#define  USBC_BP_ISCR_DPDM_PULLUP_EN		16
+#define  USBC_BP_ISCR_FORCE_ID			14
+#define  USBC_BP_ISCR_FORCE_VBUS_VALID		12
+#define  USBC_BP_ISCR_VBUS_VALID_SRC		10
+
+#define  USBC_BP_ISCR_HOSC_EN			7
+#define  USBC_BP_ISCR_VBUS_CHANGE_DETECT	6
+#define  USBC_BP_ISCR_ID_CHANGE_DETECT		5
+#define  USBC_BP_ISCR_DPDM_CHANGE_DETECT	4
+#define  USBC_BP_ISCR_IRQ_ENABLE		3
+#define  USBC_BP_ISCR_VBUS_CHANGE_DETECT_EN	2
+#define  USBC_BP_ISCR_ID_CHANGE_DETECT_EN	1
+#define  USBC_BP_ISCR_DPDM_CHANGE_DETECT_EN	0
+
+/******************************************************************************
+ * From usbc/usbc.c
+ ******************************************************************************/
+
+static u32 USBC_WakeUp_ClearChangeDetect(u32 reg_val)
+{
+	u32 temp = reg_val;
+
+	temp &= ~(1 << USBC_BP_ISCR_VBUS_CHANGE_DETECT);
+	temp &= ~(1 << USBC_BP_ISCR_ID_CHANGE_DETECT);
+	temp &= ~(1 << USBC_BP_ISCR_DPDM_CHANGE_DETECT);
+
+	return temp;
+}
+
+static void USBC_EnableIdPullUp(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val |= (1 << USBC_BP_ISCR_ID_PULLUP_EN);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_DisableIdPullUp(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val &= ~(1 << USBC_BP_ISCR_ID_PULLUP_EN);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_EnableDpDmPullUp(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val |= (1 << USBC_BP_ISCR_DPDM_PULLUP_EN);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_DisableDpDmPullUp(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val &= ~(1 << USBC_BP_ISCR_DPDM_PULLUP_EN);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_ForceIdToLow(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_ID);
+	reg_val |= (0x02 << USBC_BP_ISCR_FORCE_ID);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_ForceIdToHigh(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_ID);
+	reg_val |= (0x03 << USBC_BP_ISCR_FORCE_ID);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_ForceVbusValidDisable(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_ForceVbusValidToHigh(__iomem void *base)
+{
+	u32 reg_val;
+
+	reg_val = musb_readl(base, USBC_REG_o_ISCR);
+	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
+	reg_val |= (0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
+	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
+	musb_writel(base, USBC_REG_o_ISCR, reg_val);
+}
+
+static void USBC_ConfigFIFO_Base(void)
+{
+	u32 reg_value;
+
+	/* config usb fifo, 8kb mode */
+	reg_value = readl(SUNXI_SRAMC_BASE + 0x04);
+	reg_value &= ~(0x03 << 0);
+	reg_value |= (1 << 0);
+	writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
+}
+
+/******************************************************************************
+ * MUSB Glue code
+ ******************************************************************************/
+
+static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
+{
+	struct musb		*musb = __hci;
+	irqreturn_t		retval = IRQ_NONE;
+
+	/* read and flush interrupts */
+	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+	if (musb->int_usb)
+		musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb);
+	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+	if (musb->int_tx)
+		musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx);
+	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+	if (musb->int_rx)
+		musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx);
+
+	if (musb->int_usb || musb->int_tx || musb->int_rx)
+		retval |= musb_interrupt(musb);
+
+	return retval;
+}
+
+static void sunxi_musb_enable(struct musb *musb)
+{
+	pr_debug("%s():\n", __func__);
+
+	/* select PIO mode */
+	musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
+
+	if (is_host_enabled(musb)) {
+		/* port power on */
+		sunxi_usbc_vbus_enable(0);
+	}
+}
+
+static void sunxi_musb_disable(struct musb *musb)
+{
+	pr_debug("%s():\n", __func__);
+
+	/* Put the controller back in a pristane state for "usb reset" */
+	if (musb->is_active) {
+		sunxi_usbc_disable(0);
+		sunxi_usbc_enable(0);
+		musb->is_active = 0;
+	}
+}
+
+static int sunxi_musb_init(struct musb *musb)
+{
+	int err;
+
+	pr_debug("%s():\n", __func__);
+
+	err = sunxi_usbc_request_resources(0);
+	if (err)
+		return err;
+
+	musb->isr = sunxi_musb_interrupt;
+	sunxi_usbc_enable(0);
+
+	USBC_ConfigFIFO_Base();
+	USBC_EnableDpDmPullUp(musb->mregs);
+	USBC_EnableIdPullUp(musb->mregs);
+
+	if (is_host_enabled(musb)) {
+		/* Host mode */
+		USBC_ForceIdToLow(musb->mregs);
+		USBC_ForceVbusValidToHigh(musb->mregs);
+	} else {
+		/* Peripheral mode */
+		USBC_ForceIdToHigh(musb->mregs);
+		USBC_ForceVbusValidDisable(musb->mregs);
+	}
+
+	return 0;
+}
+
+static int sunxi_musb_exit(struct musb *musb)
+{
+	pr_debug("%s():\n", __func__);
+
+	USBC_DisableDpDmPullUp(musb->mregs);
+	USBC_DisableIdPullUp(musb->mregs);
+	sunxi_usbc_vbus_disable(0);
+	sunxi_usbc_disable(0);
+
+	return sunxi_usbc_free_resources(0);
+}
+
+const struct musb_platform_ops sunxi_musb_ops = {
+	.init		= sunxi_musb_init,
+	.exit		= sunxi_musb_exit,
+
+	.enable		= sunxi_musb_enable,
+	.disable	= sunxi_musb_disable,
+};
diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h
index 27f656f..50bad37 100644
--- a/drivers/usb/musb-new/usb-compat.h
+++ b/drivers/usb/musb-new/usb-compat.h
@@ -48,6 +48,7 @@
 	list_add_tail(&urb->urb_list, &urb->ep->urb_list);	\
 	ret; })
 #define usb_hcd_unlink_urb_from_ep(hcd, urb)	list_del_init(&urb->urb_list)
+#define usb_hcd_check_unlink_urb(hdc, urb, status)	0
 
 static inline void usb_hcd_giveback_urb(struct usb_hcd *hcd,
 					struct urb *urb,
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index be616e8..becbe3f 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -90,15 +90,8 @@
 #endif
 
 #ifdef CONFIG_CMD_USB
-#define BOOTENV_RUN_USB_INIT "run usb_init; "
-#define BOOTENV_SET_USB_NEED_INIT "setenv usb_need_init; "
+#define BOOTENV_RUN_USB_INIT "usb start; "
 #define BOOTENV_SHARED_USB \
-	"usb_init=" \
-		"if ${usb_need_init}; then " \
-			"setenv usb_need_init false; " \
-			"usb start 0; " \
-		"fi\0" \
-	\
 	"usb_boot=" \
 		BOOTENV_RUN_USB_INIT \
 		BOOTENV_SHARED_BLKDEV_BODY(usb)
@@ -106,7 +99,6 @@
 #define BOOTENV_DEV_NAME_USB	BOOTENV_DEV_NAME_BLKDEV
 #else
 #define BOOTENV_RUN_USB_INIT
-#define BOOTENV_SET_USB_NEED_INIT
 #define BOOTENV_SHARED_USB
 #define BOOTENV_DEV_USB \
 	BOOT_TARGET_DEVICES_references_USB_without_CONFIG_CMD_USB
@@ -202,7 +194,7 @@
 	\
 	BOOT_TARGET_DEVICES(BOOTENV_DEV)                                  \
 	\
-	"bootcmd=" BOOTENV_SET_USB_NEED_INIT BOOTENV_SET_SCSI_NEED_INIT   \
+	"bootcmd=" BOOTENV_SET_SCSI_NEED_INIT                             \
 		"for target in ${boot_targets}; do "                      \
 			"run bootcmd_${target}; "                         \
 		"done\0"
diff --git a/include/configs/MPC837XERDB.h b/include/configs/MPC837XERDB.h
index 8ed0f7c..19e0e30 100644
--- a/include/configs/MPC837XERDB.h
+++ b/include/configs/MPC837XERDB.h
@@ -15,6 +15,8 @@
 #define CONFIG_E300		1 /* E300 family */
 #define CONFIG_MPC837x		1 /* MPC837x CPU specific */
 #define CONFIG_MPC837XERDB	1
+#define CONFIG_DISPLAY_BOARDINFO
+#define CONFIG_SYS_GENERIC_BOARD
 
 #define	CONFIG_SYS_TEXT_BASE	0xFE000000
 
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index e839053..647cac5 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -109,6 +109,7 @@
 #define CONFIG_SYS_PBSIZE	1024	/* Print Buffer Size */
 #define CONFIG_SYS_MAXARGS	16	/* max number of command args */
 #define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_SKIP_LOWLEVEL_INIT
 
 /* Boot Argument Buffer Size */
 #define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
diff --git a/include/usb.h b/include/usb.h
index d3c7415..a8fee0b 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -120,6 +120,7 @@
 	 * Each instance needs its own set of data structures.
 	 */
 	unsigned long status;
+	unsigned long int_pending;	/* 1 bit per ep, used by int_queue */
 	int act_len;			/* transfered bytes */
 	int maxchild;			/* Number of ports if hub */
 	int portnr;
@@ -154,11 +155,16 @@
 	defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \
 	defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X) || \
 	defined(CONFIG_USB_MUSB_DSPS) || defined(CONFIG_USB_MUSB_AM35X) || \
-	defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI) || \
-	defined(CONFIG_USB_DWC2)
+	defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_MUSB_SUNXI) || \
+	defined(CONFIG_USB_XHCI) || defined(CONFIG_USB_DWC2)
 
 int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
 int usb_lowlevel_stop(int index);
+#ifdef CONFIG_MUSB_HOST
+void usb_reset_root_port(void);
+#else
+#define usb_reset_root_port()
+#endif
 
 int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
 			void *buffer, int transfer_len);
@@ -167,9 +173,9 @@
 int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 			int transfer_len, int interval);
 
-#ifdef CONFIG_USB_EHCI /* Only the ehci code has pollable int support */
+#if defined CONFIG_USB_EHCI || defined CONFIG_MUSB_HOST
 struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe,
-	int queuesize, int elementsize, void *buffer);
+	int queuesize, int elementsize, void *buffer, int interval);
 int destroy_int_queue(struct usb_device *dev, struct int_queue *queue);
 void *poll_int_queue(struct usb_device *dev, struct int_queue *queue);
 #endif