diff mbox

[OpenWrt-Devel,2/2] gemini: update usb driver and merge registers into one patch

Message ID 1418523688-11967-1-git-send-email-roman@advem.lv
State Accepted
Headers show

Commit Message

Roman Yeryomin Dec. 14, 2014, 2:21 a.m. UTC
Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 .../gemini/files/drivers/usb/host/ehci-fotg2.c     | 258 +++++++++
 .../gemini/patches-3.10/130-usb-ehci-fot2g.patch   | 223 ++++++++
 .../130-usb-ehci-gemini-fot2gxx-support.patch      | 611 ---------------------
 .../131-arm-gemini-add-usb-platform-device.patch   |  75 ---
 .../patches-3.10/132-arm-gemini-register-usb.patch |  65 +++
 .../132-arm-gemini-wbd111-register-usb.patch       |  24 -
 .../133-arm-gemini-wbd222-register-usb.patch       |  10 -
 .../134-arm-gemini-rut100-register-usb.patch       |  10 -
 .../135-arm-gemini-nas4220-register-usb.patch      |  11 -
 9 files changed, 546 insertions(+), 741 deletions(-)
 create mode 100644 target/linux/gemini/files/drivers/usb/host/ehci-fotg2.c
 create mode 100644 target/linux/gemini/patches-3.10/130-usb-ehci-fot2g.patch
 delete mode 100644 target/linux/gemini/patches-3.10/130-usb-ehci-gemini-fot2gxx-support.patch
 delete mode 100644 target/linux/gemini/patches-3.10/131-arm-gemini-add-usb-platform-device.patch
 create mode 100644 target/linux/gemini/patches-3.10/132-arm-gemini-register-usb.patch
 delete mode 100644 target/linux/gemini/patches-3.10/132-arm-gemini-wbd111-register-usb.patch
 delete mode 100644 target/linux/gemini/patches-3.10/133-arm-gemini-wbd222-register-usb.patch
 delete mode 100644 target/linux/gemini/patches-3.10/134-arm-gemini-rut100-register-usb.patch
 delete mode 100644 target/linux/gemini/patches-3.10/135-arm-gemini-nas4220-register-usb.patch
diff mbox

Patch

diff --git a/target/linux/gemini/files/drivers/usb/host/ehci-fotg2.c b/target/linux/gemini/files/drivers/usb/host/ehci-fotg2.c
new file mode 100644
index 0000000..4d95f2e
--- /dev/null
+++ b/target/linux/gemini/files/drivers/usb/host/ehci-fotg2.c
@@ -0,0 +1,258 @@ 
+/*
+ *  Gemini EHCI Host Controller driver
+ *
+ *  Copyright (C) 2014 Roman Yeryomin <roman@advem.lv>
+ *  Copyright (C) 2012 Tobias Waldvogel
+ *  based on GPLd code from Sony Computer Entertainment Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ */
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/ehci_pdriver.h>
+
+#include <mach/hardware.h>
+#include <mach/global_reg.h>
+
+#include "ehci.h"
+
+#define DRV_NAME			"ehci-fotg2"
+
+#define HCD_MISC			0x40
+
+#define OTGC_SCR			0x80
+#define OTGC_INT_STS			0x84
+#define OTGC_INT_EN			0x88
+
+#define GLOBAL_ISR			0xC0
+#define GLOBAL_ICR			0xC4
+
+#define GLOBAL_INT_POLARITY		(1 << 3)
+#define GLOBAL_INT_MASK_HC		(1 << 2)
+#define GLOBAL_INT_MASK_OTG		(1 << 1)
+#define GLOBAL_INT_MASK_DEV		(1 << 0)
+
+#define OTGC_SCR_ID			(1 << 21)
+#define OTGC_SCR_CROLE			(1 << 20)
+#define OTGC_SCR_VBUS_VLD		(1 << 19)
+#define OTGC_SCR_A_SRP_RESP_TYPE	(1 << 8)
+#define OTGC_SCR_A_SRP_DET_EN		(1 << 7)
+#define OTGC_SCR_A_SET_B_HNP_EN		(1 << 6)
+#define OTGC_SCR_A_BUS_DROP		(1 << 5)
+#define OTGC_SCR_A_BUS_REQ		(1 << 4)
+
+#define OTGC_INT_APLGRMV		(1 << 12)
+#define OTGC_INT_BPLGRMV		(1 << 11)
+#define OTGC_INT_OVC			(1 << 10)
+#define OTGC_INT_IDCHG			(1 << 9)
+#define OTGC_INT_RLCHG			(1 << 8)
+#define OTGC_INT_AVBUSERR		(1 << 5)
+#define OTGC_INT_ASRPDET		(1 << 4)
+#define OTGC_INT_BSRPDN			(1 << 0)
+
+#define OTGC_INT_A_TYPE	(		\
+ 		OTGC_INT_ASRPDET |	\
+		OTGC_INT_AVBUSERR |	\
+		OTGC_INT_OVC |		\
+		OTGC_INT_RLCHG |	\
+		OTGC_INT_IDCHG |	\
+		OTGC_INT_APLGRMV	\
+	)
+#define OTGC_INT_B_TYPE	(		\
+		OTGC_INT_AVBUSERR |	\
+		OTGC_INT_OVC |		\
+		OTGC_INT_RLCHG |	\
+		OTGC_INT_IDCHG		\
+	)
+
+
+static void fotg2_otg_init(struct usb_hcd *hcd)
+{
+	u32 val;
+
+	writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
+	       GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
+		hcd->regs + GLOBAL_ICR);
+
+	val = readl(hcd->regs + OTGC_SCR);
+	val &= ~(OTGC_SCR_A_SRP_RESP_TYPE | OTGC_SCR_A_SRP_DET_EN |
+		 OTGC_SCR_A_BUS_DROP      | OTGC_SCR_A_SET_B_HNP_EN);
+	val |= OTGC_SCR_A_BUS_REQ;
+	writel(val, hcd->regs + OTGC_SCR);
+
+	writel(OTGC_INT_A_TYPE, hcd->regs + OTGC_INT_EN);
+
+	/* setup MISC register, fixes timing problems */
+	val = readl(hcd->regs + HCD_MISC);
+	val |= 0xD;
+	writel(val, hcd->regs + HCD_MISC);
+
+	writel(~0, hcd->regs + GLOBAL_ISR);
+	writel(~0, hcd->regs + OTGC_INT_STS);
+}
+
+static int fotg2_ehci_reset(struct usb_hcd *hcd)
+{
+	int retval;
+
+	retval = ehci_setup(hcd);
+	if (retval)
+		return retval;
+
+	writel(GLOBAL_INT_POLARITY, hcd->regs + GLOBAL_ICR);
+	return 0;
+}
+
+static const struct hc_driver fotg2_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "FOTG2 EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+	.reset			= fotg2_ehci_reset,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+	.get_frame_number	= ehci_get_frame,
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#if defined(CONFIG_PM)
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static irqreturn_t fotg2_ehci_irq(int irq, void *data)
+{
+	struct usb_hcd *hcd = data;
+	u32 icr, sts;
+	irqreturn_t retval;
+
+	icr = readl(hcd->regs + GLOBAL_ICR);
+	writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
+	       GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
+		hcd->regs + GLOBAL_ICR);
+
+	retval = IRQ_NONE;
+
+	sts = ~icr;
+	sts &= GLOBAL_INT_MASK_HC | GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV;
+	sts &= readl(hcd->regs + GLOBAL_ISR);
+	writel(sts, hcd->regs + GLOBAL_ISR);
+
+	if (unlikely(sts & GLOBAL_INT_MASK_DEV)) {
+		ehci_warn(hcd_to_ehci(hcd),
+			"Received unexpected irq for device role\n");
+		retval = IRQ_HANDLED;
+	}
+
+	if (unlikely(sts & GLOBAL_INT_MASK_OTG)) {
+		u32	otg_sts;
+
+		otg_sts = readl(hcd->regs + OTGC_INT_STS);
+		writel(otg_sts, hcd->regs + OTGC_INT_STS);
+
+		ehci_warn(hcd_to_ehci(hcd),
+			"Received unexpected irq for OTG management\n");
+		retval = IRQ_HANDLED;
+	}
+
+	if (sts & GLOBAL_INT_MASK_HC) {
+		retval = IRQ_NONE;
+	}
+
+	writel(icr, hcd->regs + GLOBAL_ICR);
+	return retval;
+}
+
+static int fotg2_ehci_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int irq , err;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		pr_err("no irq provided");
+		return irq;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		pr_err("no memory resource provided");
+		return -ENXIO;
+	}
+
+	hcd = usb_create_hcd(&fotg2_ehci_hc_driver, &pdev->dev,
+			     dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
+	if (!hcd->regs) {
+		err = -ENOMEM;
+		goto err_put_hcd;
+	}
+
+	hcd->has_tt = 1;
+	hcd_to_ehci(hcd)->caps = hcd->regs;
+
+	fotg2_otg_init(hcd);
+
+	err = request_irq(irq, &fotg2_ehci_irq, IRQF_SHARED, "fotg2", hcd);
+	if (err)
+		goto err_put_hcd;
+
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_put_hcd;
+
+	platform_set_drvdata(pdev, hcd);
+	return 0;
+
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return err;
+}
+
+static int fotg2_ehci_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
+	       GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
+		hcd->regs + GLOBAL_ICR);
+
+	free_irq(hcd->irq, hcd);
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:" DRV_NAME);
+
+static struct platform_driver ehci_fotg2_driver = {
+	.probe		= fotg2_ehci_probe,
+	.remove		= fotg2_ehci_remove,
+	.driver.name	= DRV_NAME,
+};
diff --git a/target/linux/gemini/patches-3.10/130-usb-ehci-fot2g.patch b/target/linux/gemini/patches-3.10/130-usb-ehci-fot2g.patch
new file mode 100644
index 0000000..c972daf
--- /dev/null
+++ b/target/linux/gemini/patches-3.10/130-usb-ehci-fot2g.patch
@@ -0,0 +1,223 @@ 
+--- a/arch/arm/mach-gemini/devices.c	2011-04-23 01:00:16.738137491 +0200
++++ b/arch/arm/mach-gemini/devices.c	2011-04-23 01:06:55.539299920 +0200
+@@ -188,3 +188,64 @@
+ 
+ 	return platform_device_register(&ethernet_device);
+ }
++
++static struct resource usb0_resources[] = {
++	{
++		.start  = GEMINI_USB0_BASE,
++		.end    = GEMINI_USB0_BASE + 0xfff,
++		.flags  = IORESOURCE_MEM,
++	},
++	{
++		.start  = IRQ_USB0,
++		.end    = IRQ_USB0,
++		.flags  = IORESOURCE_IRQ,
++	},
++};
++
++static struct resource usb1_resources[] = {
++	{
++		.start  = GEMINI_USB1_BASE,
++		.end    = GEMINI_USB1_BASE + 0xfff,
++		.flags  = IORESOURCE_MEM,
++	},
++	{
++		.start  = IRQ_USB1,
++		.end    = IRQ_USB1,
++		.flags  = IORESOURCE_IRQ,
++	},
++};
++
++static u64 usb0_dmamask = 0xffffffffUL;
++static u64 usb1_dmamask = 0xffffffffUL;
++
++static struct platform_device usb_device[] = {
++	{
++		.name   = "ehci-fotg2",
++		.id     = 0,
++		.dev    = {
++			.dma_mask = &usb0_dmamask,
++			.coherent_dma_mask = 0xffffffff,
++		},
++		.num_resources  = ARRAY_SIZE(usb0_resources),
++		.resource       = usb0_resources,
++	},
++	{
++		.name   = "ehci-fotg2",
++		.id     = 1,
++		.dev    = {
++			.dma_mask = &usb1_dmamask,
++			.coherent_dma_mask = 0xffffffff,
++		},
++		.num_resources  = ARRAY_SIZE(usb1_resources),
++		.resource       = usb1_resources,
++	},
++};
++
++int __init platform_register_usb(unsigned int id)
++{
++	if (id > 1)
++		return -EINVAL;
++
++	return platform_device_register(&usb_device[id]);
++}
++
+--- a/arch/arm/mach-gemini/common.h	2011-04-23 01:09:31.413161153 +0200
++++ b/arch/arm/mach-gemini/common.h	2011-04-23 01:09:52.426358514 +0200
+@@ -28,6 +28,7 @@
+ 				    unsigned int nr_parts);
+ extern int platform_register_watchdog(void);
+ extern int platform_register_ethernet(struct gemini_gmac_platform_data *pdata);
++extern int platform_register_usb(unsigned int id);
+ 
+ extern void gemini_restart(char mode, const char *cmd);
+ 
+--- a/drivers/usb/Kconfig
++++ b/drivers/usb/Kconfig
+@@ -39,6 +39,7 @@ config USB_ARCH_HAS_EHCI
+ 	default y if ARCH_MXC
+ 	default y if ARCH_MXS
+ 	default y if ARCH_OMAP3
++	default y if ARCH_GEMINI
+ 	default y if ARCH_CNS3XXX
+ 	default y if ARCH_VT8500
+ 	default y if PLAT_SPEAR
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -340,12 +340,14 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
+ 	spin_lock_irq(&ehci->lock);
+ 	ehci->rh_state = EHCI_RH_HALTED;
+ 	ehci_turn_off_all_ports(ehci);
+
++#ifndef CONFIG_ARCH_GEMINI
+ 	/* make BIOS/etc use companion controller during reboot */
+ 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ 
+ 	/* unblock posted writes */
+ 	ehci_readl(ehci, &ehci->regs->configured_flag);
++#endif
+ 	spin_unlock_irq(&ehci->lock);
+ }
+ 
+@@ -600,7 +602,9 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	// Philips, Intel, and maybe others need CMD_RUN before the
+ 	// root hub will detect new devices (why?); NEC doesn't
+ 	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
++#ifndef CONFIG_ARCH_GEMINI
+ 	ehci->command |= CMD_RUN;
++#endif
+ 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ 	dbg_cmd (ehci, "init", ehci->command);
+ 
+@@ -620,9 +624,11 @@ static int ehci_run (struct usb_hcd *hcd)
+ 	 */
+ 	down_write(&ehci_cf_port_reset_rwsem);
+ 	ehci->rh_state = EHCI_RH_RUNNING;
++#ifndef CONFIG_ARCH_GEMINI
+ 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+ 	msleep(5);
++#endif
+ 	up_write(&ehci_cf_port_reset_rwsem);
+ 	ehci->last_periodic_enable = ktime_get_real();
+ 
+@@ -763,9 +769,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 		pcd_status = status;
+ 
+ 		/* resume root hub? */
++#ifndef CONFIG_ARCH_GEMINI
+ 		if (ehci->rh_state == EHCI_RH_SUSPENDED)
+ 			usb_hcd_resume_root_hub(hcd);
+-
++#endif
+ 		/* get per-port change detect bits */
+ 		if (ehci->has_ppcd)
+ 			ppcd = status >> 16;
+@@ -1228,6 +1241,11 @@ MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_AUTHOR (DRIVER_AUTHOR);
+ MODULE_LICENSE ("GPL");
+ 
++#ifdef CONFIG_ARCH_GEMINI
++#include "ehci-fotg2.c"
++#define PLATFORM_DRIVER		ehci_fotg2_driver
++#endif
++
+ #ifdef CONFIG_USB_EHCI_FSL
+ #include "ehci-fsl.c"
+ #define	PLATFORM_DRIVER		ehci_fsl_driver
+--- a/drivers/usb/host/ehci-timer.c	2012-12-24 18:35:19.695560879 +0100
++++ b/drivers/usb/host/ehci-timer.c	2012-12-24 18:39:39.813308000 +0100
+@@ -207,7 +207,9 @@
+ 
+ 	/* Clean up the mess */
+ 	ehci->rh_state = EHCI_RH_HALTED;
++#ifndef CONFIG_ARCH_GEMINI
+ 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++#endif
+ 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	ehci_work(ehci);
+ 	end_unlink_async(ehci);
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -600,7 +600,12 @@ static inline unsigned int
+ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
+ {
+ 	if (ehci_is_TDI(ehci)) {
+-		switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) {
++#ifdef CONFIG_ARCH_GEMINI
++		portsc = readl(ehci_to_hcd(ehci)->regs + 0x80);
++		switch ((portsc>>22)&3) {
++#else
++		switch ((portsc>>26)&3) {
++#endif
+ 		case 0:
+ 			return 0;
+ 		case 1:
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -912,6 +912,11 @@ static int ehci_hub_control (
+ 			/* see what we found out */
+ 			temp = check_reset_complete (ehci, wIndex, status_reg,
+ 					ehci_readl(ehci, status_reg));
++#ifdef CONFIG_ARCH_GEMINI
++			/* restart schedule */
++		 	ehci->command |= CMD_RUN;
++			ehci_writel(ehci, ehci->command, &ehci->regs->command);
++#endif
+ 		}
+ 
+ 		if (!(temp & (PORT_RESUME|PORT_RESET))) {
+--- a/include/linux/usb/ehci_def.h	2012-12-24 15:01:10.168320497 +0100
++++ b/include/linux/usb/ehci_def.h	2012-12-24 15:11:43.335575000 +0100
+@@ -110,9 +110,14 @@
+ 	u32		frame_list;	/* points to periodic list */
+ 	/* ASYNCLISTADDR: offset 0x18 */
+ 	u32		async_next;	/* address of next async queue head */
+-
++#ifndef CONFIG_ARCH_GEMINI
+ 	u32		reserved1[2];
+-
++#else
++	u32		reserved1;
++	/* PORTSC: offset 0x20 for Faraday OTG */
++	u32		port_status[1];
++#endif
++
+ 	/* TXFILLTUNING: offset 0x24 */
+ 	u32		txfill_tuning;	/* TX FIFO Tuning register */
+ #define TXFIFO_DEFAULT	(8<<16)		/* FIFO burst threshold 8 */
+@@ -123,8 +128,11 @@
+ 	u32		configured_flag;
+ #define FLAG_CF		(1<<0)		/* true: we'll support "high speed" */
+ 
++#ifndef CONFIG_ARCH_GEMINI
+ 	/* PORTSC: offset 0x44 */
+ 	u32		port_status[0];	/* up to N_PORTS */
++#endif
++
+ /* EHCI 1.1 addendum */
+ #define PORTSC_SUSPEND_STS_ACK 0
+ #define PORTSC_SUSPEND_STS_NYET 1
diff --git a/target/linux/gemini/patches-3.10/130-usb-ehci-gemini-fot2gxx-support.patch b/target/linux/gemini/patches-3.10/130-usb-ehci-gemini-fot2gxx-support.patch
deleted file mode 100644
index f4206db..0000000
--- a/target/linux/gemini/patches-3.10/130-usb-ehci-gemini-fot2gxx-support.patch
+++ /dev/null
@@ -1,611 +0,0 @@ 
---- /dev/null
-+++ b/drivers/usb/host/ehci-fotg2xx.c
-@@ -0,0 +1,459 @@
-+/*
-+ *  EHCI Host Controller driver
-+ *
-+ *  Copyright (C) 2006 Sony Computer Entertainment Inc.
-+ *  Copyright 2006 Sony Corp.
-+ *
-+ *  This program is free software; you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License as published by
-+ *  the Free Software Foundation; version 2 of the License.
-+ */
-+
-+#include <linux/platform_device.h>
-+#include <mach/hardware.h>
-+
-+#define otg_set(port, bits) writel(readl(hcd->regs + port) | bits, hcd->regs + port)
-+
-+#define otg_clear(port, bits) writel(readl(hcd->regs + port) & ~bits, hcd->regs + port)
-+
-+#define GLOBAL_ISR			0xC0
-+#define GLOBAL_ICR			0xC4
-+
-+#define HCD_MISC			0x40
-+
-+#define OTGC_SCR			0x80
-+#define OTGC_INT_EN			0x88
-+
-+#define GLOBAL_INT_POLARITY		(1 << 3)
-+#define GLOBAL_INT_MASK_HC		(1 << 2)
-+#define GLOBAL_INT_MASK_OTG		(1 << 1)
-+#define GLOBAL_INT_MASK_DEV		(1 << 0)
-+
-+#define OTGC_SCR_ID			(1 << 21)
-+#define OTGC_SCR_CROLE			(1 << 20)
-+#define OTGC_SCR_VBUS_VLD		(1 << 19)
-+#define OTGC_SCR_A_SRP_RESP_TYPE	(1 << 8)
-+#define OTGC_SCR_A_SRP_DET_EN		(1 << 7)
-+#define OTGC_SCR_A_SET_B_HNP_EN		(1 << 6)
-+#define OTGC_SCR_A_BUS_DROP		(1 << 5)
-+#define OTGC_SCR_A_BUS_REQ		(1 << 4)
-+
-+#define OTGC_INT_APLGRMV		(1 << 12)
-+#define OTGC_INT_BPLGRMV		(1 << 11)
-+#define OTGC_INT_OVC			(1 << 10)
-+#define OTGC_INT_IDCHG			(1 << 9)
-+#define OTGC_INT_RLCHG			(1 << 8)
-+#define OTGC_INT_AVBUSERR		(1 << 5)
-+#define OTGC_INT_ASRPDET		(1 << 4)
-+#define OTGC_INT_BSRPDN			(1 << 0)
-+
-+#define OTGC_INT_A_TYPE		(OTGC_INT_ASRPDET|OTGC_INT_AVBUSERR|OTGC_INT_OVC|OTGC_INT_RLCHG|OTGC_INT_IDCHG|OTGC_INT_APLGRMV)
-+#define OTGC_INT_B_TYPE		(OTGC_INT_AVBUSERR|OTGC_INT_OVC|OTGC_INT_RLCHG|OTGC_INT_IDCHG)
-+
-+static void fotg2xx_otgc_role_change(struct usb_hcd *hcd);
-+
-+static void fotg2xx_otgc_init(struct usb_hcd *hcd)
-+{
-+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-+	unsigned int reg;
-+
-+	reg = __raw_readl(hcd->regs + OTGC_SCR);
-+	ehci_info(ehci, "role detected: %s, ",
-+		  (reg & OTGC_SCR_CROLE) ? "Peripheral" : "Host");
-+
-+	if (reg & OTGC_SCR_ID)
-+		ehci_info(ehci, "B-Device (may be unsupported!)\n");
-+	else
-+		ehci_info(ehci, "A-Device\n");
-+
-+	/* Enable the SRP detect */
-+	reg &= ~OTGC_SCR_A_SRP_RESP_TYPE;
-+	__raw_writel(reg, hcd->regs + OTGC_SCR);
-+
-+	reg = __raw_readl(hcd->regs + OTGC_INT_EN);
-+	/* clear INT B: bits AVBUSERR | OVC | RLCHG | IDCHG */
-+	reg &= ~OTGC_INT_B_TYPE;
-+	/* set INT A: bits ASRPDET | AVBUSERR | OVC | RLCHG | IDCHG | APLGRMV */
-+	reg |= OTGC_INT_A_TYPE;
-+	__raw_writel(reg, hcd->regs + OTGC_INT_EN);
-+
-+	reg = __raw_readl(hcd->regs + GLOBAL_ICR);
-+	reg &= ~GLOBAL_INT_MASK_OTG;
-+	__raw_writel(reg, hcd->regs + GLOBAL_ICR);
-+
-+	/* setup MISC register, fixes timing problems */
-+	reg = __raw_readl(hcd->regs + HCD_MISC);
-+	reg |= 0xD;
-+	__raw_writel(reg, hcd->regs + HCD_MISC);
-+
-+	fotg2xx_otgc_role_change(hcd);
-+}
-+
-+static void fotg2xx_otgh_close(struct usb_hcd *hcd)
-+{
-+	unsigned int reg;
-+
-+	/* <1>.Enable Interrupt Mask */
-+	reg = __raw_readl(hcd->regs + GLOBAL_ICR);
-+	reg |= GLOBAL_INT_MASK_HC;
-+	__raw_writel(reg, hcd->regs + GLOBAL_ICR);
-+
-+	/* <2>.Clear the Interrupt status */
-+	reg = __raw_readl(hcd->regs + 0x18);
-+	reg &= 0x0000003F;
-+	__raw_writel(reg, hcd->regs + 0x14);
-+}
-+
-+static void fotg2xx_otgh_open(struct usb_hcd *hcd)
-+{
-+	unsigned int reg;
-+
-+	reg = __raw_readl(hcd->regs + OTGC_SCR);
-+	reg &= ~OTGC_SCR_A_SRP_DET_EN;
-+	__raw_writel(reg, hcd->regs + OTGC_SCR);
-+
-+	reg = __raw_readl(hcd->regs + GLOBAL_ICR);
-+	reg &= ~GLOBAL_INT_MASK_HC;
-+	__raw_writel(reg, hcd->regs + GLOBAL_ICR);
-+}
-+
-+/* change to host role */
-+static void fotg2xx_otgc_role_change(struct usb_hcd *hcd)
-+{
-+
-+	/* clear A_SET_B_HNP_EN */
-+	otg_clear(0x80, BIT(6));
-+
-+	/*** Enable VBUS driving */
-+	if (readl(hcd->regs + 0x80) & BIT(19))
-+		printk(KERN_INFO "VBUS already enabled\n");
-+	else {
-+		int cnt = 0;
-+
-+		/* clear A_BUS_DROP */
-+		otg_clear(0x80, BIT(5));
-+
-+		/* set A_BUS_REQ */
-+		otg_set(0x80, BIT(4));
-+
-+		/* set global bus reg to VBUS on */
-+		writel(readl(IO_ADDRESS(0x40000000) + 0x30) | ((BIT(21)|BIT(22))),
-+			IO_ADDRESS(0x40000000) + 0x30);
-+
-+		if (readl(hcd->regs + 0x80) & (1<<19)) {
-+			printk(KERN_INFO "Waiting for VBus");
-+			while (!(readl(hcd->regs + 0x80) & (1<<19)) && (cnt < 80)) {
-+				printk(KERN_CONT ".");
-+				cnt++;
-+			}
-+			printk(KERN_CONT "\n");
-+		} else
-+			printk(KERN_INFO "VBUS enabled.\n");
-+
-+		mdelay(1);
-+	}
-+	fotg2xx_otgh_open(hcd);
-+}
-+
-+static int fotg2xx_ehci_hc_reset(struct usb_hcd *hcd)
-+{
-+	int result;
-+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-+
-+	ehci->caps = hcd->regs;
-+	ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-+
-+	dbg_hcs_params(ehci, "reset");
-+	dbg_hcc_params(ehci, "reset");
-+
-+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-+	hcd->has_tt = 1;
-+
-+	result = ehci_halt(ehci);
-+	if (result)
-+		return result;
-+
-+	return ehci_init(hcd);
-+}
-+
-+/*
-+ * Name: OTGC_INT_ISR
-+ * Description:This interrupt service routine belongs to the OTG-Controller
-+ *           <1>.Check for ID_Change
-+ *           <2>.Check for RL_Change
-+ *           <3>.Error Detect
-+ * Input: wINTStatus
-+ * Output:void
-+ */
-+void fotg2xx_int_isr(struct usb_hcd *hcd, u32 wINTStatus)
-+{
-+	/* <1>.Check for ID_Change */
-+	if (wINTStatus&OTGC_INT_IDCHG) {
-+		if ((readl(hcd->regs + 0x80) & BIT(21)) != 0)
-+			fotg2xx_otgc_init(hcd); /* Change to B Type */
-+		else
-+			fotg2xx_otgc_init(hcd); /* Change to A Type */
-+
-+		return;
-+	}
-+
-+	/* <2>.Check for RL_Change */
-+	if (wINTStatus&OTGC_INT_RLCHG)
-+		fotg2xx_otgc_role_change(hcd);
-+
-+	/* <3>.Error Detect */
-+	if (wINTStatus&OTGC_INT_AVBUSERR)
-+		printk(KERN_ERR "VBus error!\n");
-+
-+	if (wINTStatus&OTGC_INT_OVC)
-+		printk(KERN_WARNING "Overcurrent detected!\n");
-+
-+	/* <3>.Check for Type-A/Type-B Interrupt */
-+	if ((readl(hcd->regs + 0x80) & BIT(21)) == 0) { /*For Type-A Interrupt*/
-+		if (wINTStatus & (OTGC_INT_A_TYPE | OTGC_INT_ASRPDET)) {
-+			/* <1>.SRP detected => then set global variable */
-+			printk(KERN_WARNING "SRP detected, but not implemented!\n");
-+
-+#if 0
-+			u32 wTempCounter;
-+			/* <2>.Turn on the V Bus */
-+			pFTC_OTG->otg.state = OTG_STATE_A_WAIT_VRISE;
-+			OTGC_enable_vbus_draw_storlink(1);
-+			pFTC_OTG->otg.state = OTG_STATE_A_HOST;
-+			/* <3>.Should waiting for Device-Connect Wait 300ms */
-+			INFO(pFTC_OTG, ">>> OTG-A Waiting for OTG-B Connect,\n");
-+			wTempCounter = 0;
-+			while (mwHost20_PORTSC_ConnectStatus_Rd() == 0) {
-+				mdelay(1);
-+				wTempCounter++;
-+				/* Waiting for 300 ms */
-+				if (wTempCounter > 300) {
-+					mdwOTGC_Control_A_SRP_DET_EN_Clr();
-+					INFO(pFTC_OTG, ">>> OTG-B do not connect under 300 ms...\n");
-+					break;
-+				}
-+			}
-+			/* <4>.If Connect => issue quick Reset */
-+			if (mwHost20_PORTSC_ConnectStatus_Rd() > 0) {
-+				mdelay(300); /* For OPT-A Test */
-+				OTGH_host_quick_Reset();
-+				OTGH_Open();
-+				pFTC_OTG->otg.host->A_Disable_Set_Feature_HNP = 0;
-+			}
-+#endif
-+		}
-+	} else { /* For Type-B Interrupt */
-+		BUG();
-+	}
-+}
-+
-+static irqreturn_t fotg2xx_ehci_irq(int irq, void *devid)
-+{
-+	struct usb_hcd *hcd = devid;
-+	u32 val;
-+
-+	/* OTG Interrupt Status Register */
-+	val = readl(hcd->regs + 0x84);
-+
-+	/* OTG stuff */
-+	if (val) {
-+		/* supposed to do "INT STS Clr" - XXX */
-+		writel(readl(hcd->regs + 0x84) | val, hcd->regs + 0x84);
-+
-+		fotg2xx_int_isr(hcd, val);
-+
-+		/* supposed to do "INT STS Clr" - XXX */
-+		writel(readl(hcd->regs + 0x84) | val, hcd->regs + 0x84);
-+
-+		return IRQ_HANDLED;
-+	}
-+
-+	if ((readl(hcd->regs + 0x80) & BIT(20)) == 0) { /* Role is HOST */
-+		if (readl(hcd->regs + 0xC0) & BIT(2)) { /* INT STS HOST */
-+			/* leave this for ehci irq handler */
-+			return IRQ_NONE;
-+		}
-+	} else
-+		printk(KERN_WARNING
-+		      "received irq for peripheral - don't know what to do!\n");
-+
-+	/* do not call the ehci irq handler */
-+	return IRQ_HANDLED;
-+}
-+
-+static int fotg2xx_ehci_run(struct usb_hcd *hcd)
-+{
-+	int retval;
-+
-+	retval = ehci_run(hcd);
-+
-+	fotg2xx_otgh_close(hcd);
-+	fotg2xx_otgc_init(hcd);
-+
-+	return retval;
-+}
-+
-+static const struct hc_driver fotg2xx_ehci_hc_driver = {
-+	.description		= hcd_name,
-+	.product_desc		= "FOTG2XX EHCI Host Controller",
-+	.hcd_priv_size		= sizeof(struct ehci_hcd),
-+	.irq			= ehci_irq,
-+	.flags			= HCD_MEMORY | HCD_USB2,
-+	.reset			= fotg2xx_ehci_hc_reset,
-+	.start			= fotg2xx_ehci_run,
-+	.stop			= ehci_stop,
-+	.shutdown		= ehci_shutdown,
-+
-+	.urb_enqueue		= ehci_urb_enqueue,
-+	.urb_dequeue		= ehci_urb_dequeue,
-+	.endpoint_disable	= ehci_endpoint_disable,
-+	.endpoint_reset		= ehci_endpoint_reset,
-+
-+	.get_frame_number	= ehci_get_frame,
-+
-+	.hub_status_data	= ehci_hub_status_data,
-+	.hub_control		= ehci_hub_control,
-+#if defined(CONFIG_PM)
-+	.bus_suspend		= ehci_bus_suspend,
-+	.bus_resume		= ehci_bus_resume,
-+#endif
-+	.relinquish_port	= ehci_relinquish_port,
-+	.port_handed_over	= ehci_port_handed_over,
-+
-+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-+};
-+
-+static int fotg2xx_ehci_probe(struct platform_device *pdev)
-+{
-+	const struct hc_driver *driver = &fotg2xx_ehci_hc_driver;
-+	struct usb_hcd *hcd;
-+	struct resource *res;
-+	int irq;
-+	int retval;
-+
-+	pr_debug("initializing FOTG2XX-SOC USB Controller\n");
-+
-+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+	if (!res) {
-+		dev_err(&pdev->dev,
-+			"Found HC with no IRQ. Check %s setup!\n",
-+			dev_name(&pdev->dev));
-+		return -ENODEV;
-+	}
-+
-+	irq = res->start;
-+
-+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-+	if (!hcd) {
-+		retval = -ENOMEM;
-+		goto err1;
-+	}
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	if (!res) {
-+		dev_err(&pdev->dev,
-+			"Found HC with no register addr. Check %s setup!\n",
-+			dev_name(&pdev->dev));
-+		retval = -ENODEV;
-+		goto err2;
-+	}
-+
-+	hcd->rsrc_start = res->start;
-+	hcd->rsrc_len = res->end - res->start + 1;
-+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-+				driver->description)) {
-+		dev_dbg(&pdev->dev, "controller already in use\n");
-+		retval = -EBUSY;
-+		goto err2;
-+	}
-+
-+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-+	if (hcd->regs == NULL) {
-+		dev_dbg(&pdev->dev, "error mapping memory\n");
-+		retval = -EFAULT;
-+		goto err3;
-+	}
-+
-+
-+	/* set global reg to mini-A host */
-+	writel(readl(IO_ADDRESS(0x40000000) + 0x30) & ~(BIT(30)|BIT(29)),
-+		IO_ADDRESS(0x40000000) + 0x30);
-+
-+	/* USB0&USB1 - VBUS off */
-+	writel(readl(IO_ADDRESS(0x40000000) + 0x30) & ~(BIT(21)|BIT(22)),
-+		IO_ADDRESS(0x40000000) + 0x30);
-+
-+	if ((readl(hcd->regs) == 0x01000010) &&
-+		(readl(hcd->regs + 4) == 0x00000001) &&
-+		(readl(hcd->regs + 8) == 0x00000006)) {
-+		dev_info(&pdev->dev,
-+			"Found Faraday OTG 2XX controller (base = 0x%08lX)\n",
-+			(unsigned long) hcd->rsrc_start);
-+	} else {
-+		dev_err(&pdev->dev, "fotg2xx id mismatch: found %d.%d.%d\n",
-+			readl(hcd->regs + 0x00),
-+			readl(hcd->regs + 0x04),
-+			readl(hcd->regs + 0x08));
-+		retval = -ENODEV;
-+		goto err4;
-+	}
-+
-+	platform_set_drvdata(pdev, hcd);
-+
-+	/* mask interrupts - peripheral, otg, host, hi-active (bits 0,1,2,3) */
-+	otg_set(0xc4, BIT(3)); /* hi active */
-+
-+	otg_set(0xc4, BIT(2)); /* host */
-+	otg_set(0xc4, BIT(1)); /* otg */
-+	otg_set(0xc4, BIT(0)); /* peripheral */
-+
-+	/* register additional interrupt - here we check otg status */
-+	if ((request_irq(irq, &fotg2xx_ehci_irq, IRQF_SHARED | IRQF_DISABLED,
-+		hcd->irq_descr, hcd)) != 0) {
-+		dev_dbg(&pdev->dev, "error requesting irq %d\n", irq);
-+		retval = -EFAULT;
-+		goto err4;
-+	}
-+
-+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-+	if (retval != 0)
-+		goto err4;
-+	return retval;
-+
-+err4:
-+	iounmap(hcd->regs);
-+err3:
-+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-+err2:
-+	usb_put_hcd(hcd);
-+err1:
-+	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
-+	return retval;
-+}
-+
-+/* may be called without controller electrically present */
-+/* may be called with controller, bus, and devices active */
-+
-+int fotg2xx_ehci_remove(struct platform_device *pdev)
-+{
-+	struct usb_hcd *hcd =
-+		(struct usb_hcd *)platform_get_drvdata(pdev);
-+
-+	usb_remove_hcd(hcd);
-+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-+	iounmap(hcd->regs);
-+	usb_put_hcd(hcd);
-+	platform_set_drvdata(pdev, NULL);
-+
-+	return 0;
-+}
-+
-+MODULE_ALIAS("platform:ehci-fotg2xx");
-+
-+static struct platform_driver fotg2xx_ehci_driver = {
-+	.probe = fotg2xx_ehci_probe,
-+	.remove = fotg2xx_ehci_remove,
-+	.driver = {
-+		.name = "ehci-fotg2xx",
-+	},
-+};
---- a/drivers/usb/host/ehci.h
-+++ b/drivers/usb/host/ehci.h
-@@ -603,7 +603,12 @@ static inline unsigned int
- ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
- {
- 	if (ehci_is_TDI(ehci)) {
-+#ifdef CONFIG_ARCH_GEMINI
-+		portsc = readl(ehci_to_hcd(ehci)->regs + 0x80);
-+		switch ((portsc>>22)&3) {
-+#else
- 		switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) {
-+#endif
- 		case 0:
- 			return 0;
- 		case 1:
---- a/drivers/usb/host/ehci-hcd.c
-+++ b/drivers/usb/host/ehci-hcd.c
-@@ -204,10 +204,12 @@ static int ehci_halt (struct ehci_hcd *e
- 	 * This routine gets called during probe before ehci->command
- 	 * has been initialized, so we can't rely on its value.
- 	 */
-+#ifndef CONFIG_ARCH_GEMINI
- 	ehci->command &= ~CMD_RUN;
- 	temp = ehci_readl(ehci, &ehci->regs->command);
- 	temp &= ~(CMD_RUN | CMD_IAAD);
- 	ehci_writel(ehci, temp, &ehci->regs->command);
-+#endif
- 
- 	spin_unlock_irq(&ehci->lock);
- 	synchronize_irq(ehci_to_hcd(ehci)->irq);
-@@ -257,13 +259,17 @@ static int ehci_reset (struct ehci_hcd *
- 	if (ehci->has_hostpc) {
- 		ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
- 				&ehci->regs->usbmode_ex);
-+#ifndef CONFIG_ARCH_GEMINI
- 		ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning);
-+#endif
- 	}
- 	if (retval)
- 		return retval;
- 
-+#ifndef CONFIG_ARCH_GEMINI
- 	if (ehci_is_TDI(ehci))
- 		tdi_reset (ehci);
-+#endif
- 
- 	if (ehci->debug)
- 		dbgp_external_startup(ehci_to_hcd(ehci));
-@@ -341,11 +347,14 @@ static void ehci_silence_controller(stru
- 	ehci->rh_state = EHCI_RH_HALTED;
- 	ehci_turn_off_all_ports(ehci);
- 
-+#ifndef CONFIG_ARCH_GEMINI
- 	/* make BIOS/etc use companion controller during reboot */
- 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
- 
- 	/* unblock posted writes */
- 	ehci_readl(ehci, &ehci->regs->configured_flag);
-+#endif
-+
- 	spin_unlock_irq(&ehci->lock);
- }
- 
-@@ -603,7 +612,9 @@ static int ehci_run (struct usb_hcd *hcd
- 	// Philips, Intel, and maybe others need CMD_RUN before the
- 	// root hub will detect new devices (why?); NEC doesn't
- 	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
-+#ifndef CONFIG_ARCH_GEMINI
- 	ehci->command |= CMD_RUN;
-+#endif
- 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
- 	dbg_cmd (ehci, "init", ehci->command);
- 
-@@ -623,9 +634,11 @@ static int ehci_run (struct usb_hcd *hcd
- 	 */
- 	down_write(&ehci_cf_port_reset_rwsem);
- 	ehci->rh_state = EHCI_RH_RUNNING;
-+#ifndef CONFIG_ARCH_GEMINI
- 	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
- 	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
- 	msleep(5);
-+#endif /* !CONFIG_ARCH_GEMINI */
- 	up_write(&ehci_cf_port_reset_rwsem);
- 	ehci->last_periodic_enable = ktime_get_real();
- 
-@@ -1228,6 +1241,11 @@ MODULE_DESCRIPTION(DRIVER_DESC);
- MODULE_AUTHOR (DRIVER_AUTHOR);
- MODULE_LICENSE ("GPL");
- 
-+#ifdef CONFIG_ARCH_GEMINI
-+#include "ehci-fotg2xx.c"
-+#define PLATFORM_DRIVER		fotg2xx_ehci_driver
-+#endif
-+
- #ifdef CONFIG_USB_EHCI_FSL
- #include "ehci-fsl.c"
- #define	PLATFORM_DRIVER		ehci_fsl_driver
---- a/drivers/usb/host/ehci-hub.c
-+++ b/drivers/usb/host/ehci-hub.c
-@@ -914,6 +914,12 @@ static int ehci_hub_control (
- 			/* see what we found out */
- 			temp = check_reset_complete (ehci, wIndex, status_reg,
- 					ehci_readl(ehci, status_reg));
-+#ifdef CONFIG_ARCH_GEMINI
-+			/* restart schedule */
-+			ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) | CMD_RUN, &ehci->regs->command);
-+
-+//			hcd->state = HC_STATE_RUNNING;
-+#endif
- 		}
- 
- 		if (!(temp & (PORT_RESUME|PORT_RESET))) {
---- a/drivers/usb/Kconfig
-+++ b/drivers/usb/Kconfig
-@@ -47,6 +47,7 @@ config USB_ARCH_HAS_EHCI
- 	default y if MICROBLAZE
- 	default y if SPARC_LEON
- 	default y if ARCH_MMP
-+	default y if ARCH_GEMINI
- 	default y if MACH_LOONGSON1
- 	default y if PLAT_ORION
- 	default PCI
-@@ -96,7 +97,7 @@ config USB
- 	  traditional PC serial port.  The bus supplies power to peripherals
- 	  and allows for hot swapping.  Up to 127 USB peripherals can be
- 	  connected to a single USB host in a tree structure.
--	  
-+
- 	  The USB host is the root of the tree, the peripherals are the
- 	  leaves and the inner nodes are special USB devices called hubs.
- 	  Most PCs now have USB host ports, used to connect peripherals
---- a/include/linux/usb/ehci_def.h
-+++ b/include/linux/usb/ehci_def.h
-@@ -111,6 +111,7 @@ struct ehci_regs {
- 	/* ASYNCLISTADDR: offset 0x18 */
- 	u32		async_next;	/* address of next async queue head */
- 
-+#ifndef CONFIG_ARCH_GEMINI
- 	u32		reserved1[2];
- 
- 	/* TXFILLTUNING: offset 0x24 */
-@@ -118,6 +119,7 @@ struct ehci_regs {
- #define TXFIFO_DEFAULT	(8<<16)		/* FIFO burst threshold 8 */
- 
- 	u32		reserved2[6];
-+#endif /* !CONFIG_ARCH_GEMINI */
- 
- 	/* CONFIGFLAG: offset 0x40 */
- 	u32		configured_flag;
diff --git a/target/linux/gemini/patches-3.10/131-arm-gemini-add-usb-platform-device.patch b/target/linux/gemini/patches-3.10/131-arm-gemini-add-usb-platform-device.patch
deleted file mode 100644
index d1a4fee..0000000
--- a/target/linux/gemini/patches-3.10/131-arm-gemini-add-usb-platform-device.patch
+++ /dev/null
@@ -1,75 +0,0 @@ 
---- a/arch/arm/mach-gemini/devices.c
-+++ b/arch/arm/mach-gemini/devices.c
-@@ -185,3 +185,62 @@ int __init platform_register_ethernet(st
- 
- 	return platform_device_register(&ethernet_device);
- }
-+
-+static u64 usb0_dmamask = DMA_BIT_MASK(32);
-+static struct resource usb0_resources[] = {
-+	{
-+		.start	= 0x68000000,
-+		.end	= 0x68000fff,
-+		.flags	= IORESOURCE_MEM,
-+	},
-+	{
-+		.start	= IRQ_USB0,
-+		.end	= IRQ_USB0,
-+		.flags	= IORESOURCE_IRQ,
-+	},
-+};
-+
-+static u64 usb1_dmamask = DMA_BIT_MASK(32);
-+static struct resource usb1_resources[] = {
-+	{
-+		.start	= 0x69000000,
-+		.end	= 0x69000fff,
-+		.flags	= IORESOURCE_MEM,
-+	},
-+	{
-+		.start	= IRQ_USB1,
-+		.end	= IRQ_USB1,
-+		.flags	= IORESOURCE_IRQ,
-+	},
-+};
-+
-+static struct platform_device usb_device[] = {
-+	{
-+		.name	= "ehci-fotg2xx",
-+		.id	= 0,
-+		.dev	= {
-+			.dma_mask = &usb0_dmamask,
-+			.coherent_dma_mask = DMA_BIT_MASK(32),
-+		},
-+		.num_resources	= ARRAY_SIZE(usb0_resources),
-+		.resource	= usb0_resources,
-+	},
-+	{
-+		.name	= "ehci-fotg2xx",
-+		.id	= 1,
-+		.dev	= {
-+			.dma_mask = &usb1_dmamask,
-+			.coherent_dma_mask = DMA_BIT_MASK(32),
-+		},
-+		.num_resources	= ARRAY_SIZE(usb1_resources),
-+		.resource	= usb1_resources,
-+	},
-+};
-+
-+int __init platform_register_usb(unsigned int id)
-+{
-+	if (id > 1)
-+		return -EINVAL;
-+
-+	return platform_device_register(&usb_device[id]);
-+}
---- a/arch/arm/mach-gemini/common.h
-+++ b/arch/arm/mach-gemini/common.h
-@@ -28,6 +28,7 @@ extern int platform_register_pflash(unsi
- 				    unsigned int nr_parts);
- extern int platform_register_watchdog(void);
- extern int platform_register_ethernet(struct gemini_gmac_platform_data *pdata);
-+extern int platform_register_usb(unsigned int id);
- 
- extern void gemini_restart(char mode, const char *cmd);
- 
diff --git a/target/linux/gemini/patches-3.10/132-arm-gemini-register-usb.patch b/target/linux/gemini/patches-3.10/132-arm-gemini-register-usb.patch
new file mode 100644
index 0000000..87a063c
--- /dev/null
+++ b/target/linux/gemini/patches-3.10/132-arm-gemini-register-usb.patch
@@ -0,0 +1,65 @@ 
+--- a/arch/arm/mach-gemini/board-wbd111.c
++++ b/arch/arm/mach-gemini/board-wbd111.c
+@@ -145,6 +145,7 @@ static void __init wbd111_init(void)
+ 	platform_register_watchdog();
+ 	platform_device_register(&wbd111_phy_device);
+ 	platform_register_ethernet(&gmac_data);
++	platform_register_usb(0);
+ }
+ 
+ MACHINE_START(WBD111, "Wiliboard WBD-111")
+--- a/arch/arm/mach-gemini/board-wbd222.c
++++ b/arch/arm/mach-gemini/board-wbd222.c
+@@ -147,6 +147,7 @@ static void __init wbd222_init(void)
+ 	platform_register_watchdog();
+ 	platform_device_register(&wbd222_phy_device);
+ 	platform_register_ethernet(&gmac_data);
++	platform_register_usb(0);
+ }
+ 
+ MACHINE_START(WBD222, "Wiliboard WBD-222")
+--- a/arch/arm/mach-gemini/board-rut1xx.c
++++ b/arch/arm/mach-gemini/board-rut1xx.c
+@@ -105,6 +105,7 @@ static void __init rut1xx_init(void)
+ 	platform_register_watchdog();
+ 	platform_device_register(&rut1xx_phy_device);
+ 	platform_register_ethernet(&gmac_data);
++	platform_register_usb(0);
+ }
+ 
+ MACHINE_START(RUT100, "Teltonika RUT100")
+--- a/arch/arm/mach-gemini/board-nas4220b.c
++++ b/arch/arm/mach-gemini/board-nas4220b.c
+@@ -134,10 +134,23 @@
+ 		GLOBAL_ARBITRATION1_CTRL));
+ }
+ 
++static void __init usb_ib4220b_init(void)
++{
++	unsigned int val;
++
++	val = readl((void __iomem*)(IO_ADDRESS(GEMINI_GLOBAL_BASE) +
++		GLOBAL_MISC_CTRL));
++	val &= ~(USB0_PLUG_MINIB | USB1_PLUG_MINIB);
++	val |= USB0_VBUS_ON | USB1_VBUS_ON;
++	writel(val, (void __iomem*)(IO_ADDRESS(GEMINI_GLOBAL_BASE) +
++		GLOBAL_MISC_CTRL));
++}
++
+ static void __init ib4220b_init(void)
+ {
+ 	gemini_gpio_init();
+ 	ib4220b_gmac_init();
++	usb_ib4220b_init();
+ 	platform_register_uart();
+ 	platform_register_pflash(SZ_16M, NULL, 0);
+ 	platform_device_register(&ib4220b_led_device);
+@@ -168,6 +168,8 @@ static void __init ib4220b_init(void)
+ 	platform_register_watchdog();
+ 	platform_device_register(&ib4220b_phy_device);
+ 	platform_register_ethernet(&ib4220b_gmac_data);
++	platform_register_usb(0);
++	platform_register_usb(1);
+ }
+ 
+ MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
diff --git a/target/linux/gemini/patches-3.10/132-arm-gemini-wbd111-register-usb.patch b/target/linux/gemini/patches-3.10/132-arm-gemini-wbd111-register-usb.patch
deleted file mode 100644
index 44e72d1..0000000
--- a/target/linux/gemini/patches-3.10/132-arm-gemini-wbd111-register-usb.patch
+++ /dev/null
@@ -1,24 +0,0 @@ 
---- a/arch/arm/mach-gemini/board-wbd111.c
-+++ b/arch/arm/mach-gemini/board-wbd111.c
-@@ -145,6 +145,7 @@ static void __init wbd111_init(void)
- 	platform_register_watchdog();
- 	platform_device_register(&wbd111_phy_device);
- 	platform_register_ethernet(&gmac_data);
-+	platform_register_usb(0);
- }
- 
- MACHINE_START(WBD111, "Wiliboard WBD-111")
---- a/drivers/usb/host/ehci-hcd.c
-+++ b/drivers/usb/host/ehci-hcd.c
-@@ -99,7 +99,11 @@ module_param (park, uint, S_IRUGO);
- MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
- 
- /* for flakey hardware, ignore overcurrent indicators */
-+#ifdef CONFIG_ARCH_GEMINI
-+static bool ignore_oc = 1;
-+#else
- static bool ignore_oc = 0;
-+#endif
- module_param (ignore_oc, bool, S_IRUGO);
- MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
- 
diff --git a/target/linux/gemini/patches-3.10/133-arm-gemini-wbd222-register-usb.patch b/target/linux/gemini/patches-3.10/133-arm-gemini-wbd222-register-usb.patch
deleted file mode 100644
index 2adc410..0000000
--- a/target/linux/gemini/patches-3.10/133-arm-gemini-wbd222-register-usb.patch
+++ /dev/null
@@ -1,10 +0,0 @@ 
---- a/arch/arm/mach-gemini/board-wbd222.c
-+++ b/arch/arm/mach-gemini/board-wbd222.c
-@@ -147,6 +147,7 @@ static void __init wbd222_init(void)
- 	platform_register_watchdog();
- 	platform_device_register(&wbd222_phy_device);
- 	platform_register_ethernet(&gmac_data);
-+	platform_register_usb(0);
- }
- 
- MACHINE_START(WBD222, "Wiliboard WBD-222")
diff --git a/target/linux/gemini/patches-3.10/134-arm-gemini-rut100-register-usb.patch b/target/linux/gemini/patches-3.10/134-arm-gemini-rut100-register-usb.patch
deleted file mode 100644
index c3755ee..0000000
--- a/target/linux/gemini/patches-3.10/134-arm-gemini-rut100-register-usb.patch
+++ /dev/null
@@ -1,10 +0,0 @@ 
---- a/arch/arm/mach-gemini/board-rut1xx.c
-+++ b/arch/arm/mach-gemini/board-rut1xx.c
-@@ -105,6 +105,7 @@ static void __init rut1xx_init(void)
- 	platform_register_watchdog();
- 	platform_device_register(&rut1xx_phy_device);
- 	platform_register_ethernet(&gmac_data);
-+	platform_register_usb(0);
- }
- 
- MACHINE_START(RUT100, "Teltonika RUT100")
diff --git a/target/linux/gemini/patches-3.10/135-arm-gemini-nas4220-register-usb.patch b/target/linux/gemini/patches-3.10/135-arm-gemini-nas4220-register-usb.patch
deleted file mode 100644
index 078c6c2..0000000
--- a/target/linux/gemini/patches-3.10/135-arm-gemini-nas4220-register-usb.patch
+++ /dev/null
@@ -1,11 +0,0 @@ 
---- a/arch/arm/mach-gemini/board-nas4220b.c
-+++ b/arch/arm/mach-gemini/board-nas4220b.c
-@@ -146,6 +146,8 @@ static void __init ib4220b_init(void)
- 	platform_register_watchdog();
- 	platform_device_register(&ib4220b_phy_device);
- 	platform_register_ethernet(&ib4220b_gmac_data);
-+	platform_register_usb(0);
-+	platform_register_usb(1);
- }
- 
- MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")