[linux-yocto] [PATCH 15/65] usb: add owl usb driver

Jiang Lu lu.jiang at windriver.com
Wed Dec 21 01:16:16 PST 2016


From: wurui <wurui at actions-semi.com>

commit 5b2ea66f1539600f19ffc54bb9ea170bc4634c58 from
https://github.com/xapp-le/kernel.git

Change-Id: I963b06334ef94324ccde58f1238d15b033417e6e
---
 drivers/hid/hid-magicmouse.c                 |    3 +-
 drivers/hid/hid-ntrig.c                      |    6 +-
 drivers/usb/Kconfig                          |    1 +
 drivers/usb/Makefile                         |    2 +
 drivers/usb/dwc3/Kconfig                     |    9 +
 drivers/usb/dwc3/Makefile                    |    1 +
 drivers/usb/dwc3/core.c                      |  455 ++-
 drivers/usb/dwc3/core.h                      |    5 +
 drivers/usb/dwc3/dwc3-actions.c              |  516 +++
 drivers/usb/dwc3/ep0.c                       |   31 +-
 drivers/usb/dwc3/gadget.c                    |  155 +-
 drivers/usb/dwc3/gadget.h                    |   14 +
 drivers/usb/dwc3/hotplug_handle.c            |  237 ++
 drivers/usb/dwc3/irqs.h                      |  127 +
 drivers/usb/dwc3/usb3_regs.h                 |  136 +
 drivers/usb/gadget/Kconfig                   |   13 +
 drivers/usb/gadget/composite.c               |   11 +-
 drivers/usb/gadget/function/f_mass_storage.c |   16 +-
 drivers/usb/gadget/function/storage_common.c |   18 +
 drivers/usb/gadget/legacy/Makefile           |    3 +
 drivers/usb/gadget/legacy/adfuserver.c       | 4987 ++++++++++++++++++++++++++
 drivers/usb/gadget/legacy/adfuserver.h       |   85 +
 drivers/usb/gadget/usbstring.c               |  112 +-
 drivers/usb/host/Kconfig                     |    7 +
 drivers/usb/host/Makefile                    |    5 +-
 drivers/usb/host/aotg_debug.c                |  985 +++++
 drivers/usb/host/aotg_debug.h                |   88 +
 drivers/usb/host/aotg_hcd.c                  | 4168 +++++++++++++++++++++
 drivers/usb/host/aotg_hcd.h                  |  467 +++
 drivers/usb/host/aotg_mon.c                  |  386 ++
 drivers/usb/host/aotg_mon.h                  |   11 +
 drivers/usb/host/aotg_plat_data.h            |   22 +
 drivers/usb/host/aotg_regs.h                 | 1527 ++++++++
 drivers/usb/host/aotg_ring.c                 | 1509 ++++++++
 drivers/usb/host/aotg_ring.h                 |   48 +
 drivers/usb/host/uhost_hotplug_handle.c      |   34 +
 drivers/usb/host/xhci.c                      |   71 +
 drivers/usb/host/xhci_ss_phy_setting.c       |  131 +
 drivers/usb/host/xhci_ss_retry_mode.c        |  224 ++
 drivers/usb/host/xhci_usb3_regs.h            |   79 +
 drivers/usb/monitor/Kconfig                  |   23 +
 drivers/usb/monitor/Makefile                 |   10 +
 drivers/usb/monitor/aotg_regs.h              |  162 +
 drivers/usb/monitor/umonitor_api.c           | 1341 +++++++
 drivers/usb/monitor/umonitor_config.h        |  108 +
 drivers/usb/monitor/umonitor_core.c          | 1016 ++++++
 drivers/usb/monitor/umonitor_core.h          |  130 +
 drivers/usb/monitor/umonitor_hal.c           |  534 +++
 drivers/usb/monitor/umonitor_hal.h           |  108 +
 drivers/usb/serial/option.c                  |  272 +-
 drivers/usb/storage/usb.c                    |   33 +
 51 files changed, 20378 insertions(+), 64 deletions(-)
 mode change 100644 => 100755 drivers/hid/hid-magicmouse.c
 mode change 100644 => 100755 drivers/hid/hid-ntrig.c
 mode change 100644 => 100755 drivers/usb/Kconfig
 mode change 100644 => 100755 drivers/usb/Makefile
 mode change 100644 => 100755 drivers/usb/dwc3/Kconfig
 mode change 100644 => 100755 drivers/usb/dwc3/Makefile
 mode change 100644 => 100755 drivers/usb/dwc3/core.c
 mode change 100644 => 100755 drivers/usb/dwc3/core.h
 create mode 100644 drivers/usb/dwc3/dwc3-actions.c
 mode change 100644 => 100755 drivers/usb/dwc3/ep0.c
 mode change 100644 => 100755 drivers/usb/dwc3/gadget.c
 mode change 100644 => 100755 drivers/usb/dwc3/gadget.h
 create mode 100644 drivers/usb/dwc3/hotplug_handle.c
 create mode 100644 drivers/usb/dwc3/irqs.h
 create mode 100644 drivers/usb/dwc3/usb3_regs.h
 mode change 100644 => 100755 drivers/usb/gadget/Kconfig
 mode change 100644 => 100755 drivers/usb/gadget/composite.c
 mode change 100644 => 100755 drivers/usb/gadget/function/f_mass_storage.c
 mode change 100644 => 100755 drivers/usb/gadget/function/storage_common.c
 mode change 100644 => 100755 drivers/usb/gadget/legacy/Makefile
 create mode 100644 drivers/usb/gadget/legacy/adfuserver.c
 create mode 100644 drivers/usb/gadget/legacy/adfuserver.h
 mode change 100644 => 100755 drivers/usb/gadget/usbstring.c
 mode change 100644 => 100755 drivers/usb/host/Kconfig
 mode change 100644 => 100755 drivers/usb/host/Makefile
 create mode 100644 drivers/usb/host/aotg_debug.c
 create mode 100644 drivers/usb/host/aotg_debug.h
 create mode 100644 drivers/usb/host/aotg_hcd.c
 create mode 100644 drivers/usb/host/aotg_hcd.h
 create mode 100644 drivers/usb/host/aotg_mon.c
 create mode 100644 drivers/usb/host/aotg_mon.h
 create mode 100644 drivers/usb/host/aotg_plat_data.h
 create mode 100644 drivers/usb/host/aotg_regs.h
 create mode 100644 drivers/usb/host/aotg_ring.c
 create mode 100644 drivers/usb/host/aotg_ring.h
 create mode 100644 drivers/usb/host/uhost_hotplug_handle.c
 mode change 100644 => 100755 drivers/usb/host/xhci.c
 create mode 100644 drivers/usb/host/xhci_ss_phy_setting.c
 create mode 100644 drivers/usb/host/xhci_ss_retry_mode.c
 create mode 100644 drivers/usb/host/xhci_usb3_regs.h
 create mode 100644 drivers/usb/monitor/Kconfig
 create mode 100644 drivers/usb/monitor/Makefile
 create mode 100644 drivers/usb/monitor/aotg_regs.h
 create mode 100644 drivers/usb/monitor/umonitor_api.c
 create mode 100644 drivers/usb/monitor/umonitor_config.h
 create mode 100644 drivers/usb/monitor/umonitor_core.c
 create mode 100644 drivers/usb/monitor/umonitor_core.h
 create mode 100644 drivers/usb/monitor/umonitor_hal.c
 create mode 100644 drivers/usb/monitor/umonitor_hal.h
 mode change 100644 => 100755 drivers/usb/serial/option.c
 mode change 100644 => 100755 drivers/usb/storage/usb.c

diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
old mode 100644
new mode 100755
index 29a74c1..a3c5dad
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -471,7 +471,7 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
 	return 0;
 }
 
-static void magicmouse_input_configured(struct hid_device *hdev,
+static int magicmouse_input_configured(struct hid_device *hdev,
 		struct hid_input *hi)
 
 {
@@ -483,6 +483,7 @@ static void magicmouse_input_configured(struct hid_device *hdev,
 		/* clean msc->input to notify probe() of the failure */
 		msc->input = NULL;
 	}
+	return ret;
 }
 
 
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
old mode 100644
new mode 100755
index 600f207..756d1ef
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -859,14 +859,14 @@ not_claimed_input:
 	return 1;
 }
 
-static void ntrig_input_configured(struct hid_device *hid,
+static int ntrig_input_configured(struct hid_device *hid,
 		struct hid_input *hidinput)
 
 {
 	struct input_dev *input = hidinput->input;
 
 	if (hidinput->report->maxfield < 1)
-		return;
+		return 0;
 
 	switch (hidinput->report->field[0]->application) {
 	case HID_DG_PEN:
@@ -890,6 +890,8 @@ static void ntrig_input_configured(struct hid_device *hid,
 							"N-Trig MultiTouch";
 		break;
 	}
+
+	return 0;
 }
 
 static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
old mode 100644
new mode 100755
index 8ed451d..1074941
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -80,6 +80,7 @@ source "drivers/usb/core/Kconfig"
 
 source "drivers/usb/mon/Kconfig"
 
+source "drivers/usb/monitor/Kconfig"
 source "drivers/usb/wusbcore/Kconfig"
 
 source "drivers/usb/host/Kconfig"
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
old mode 100644
new mode 100755
index d8926c6..059faed
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_USB_ISP1760)	+= isp1760/
 
 obj-$(CONFIG_USB_MON)		+= mon/
 
+obj-$(CONFIG_USB_ACTIONS_MON)		+= monitor/
+
 obj-$(CONFIG_PCI)		+= host/
 obj-$(CONFIG_USB_EHCI_HCD)	+= host/
 obj-$(CONFIG_USB_ISP116X_HCD)	+= host/
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
old mode 100644
new mode 100755
index 473bfaa..66b6c68
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -96,6 +96,15 @@ config USB_DWC3_ST
 	  inside (i.e. STiH407).
 	  Say 'Y' or 'M' if you have one such device.
 
+config USB_DWC3_ACT
+	tristate "Actions S500 Platforms"
+	depends on ARCH_OWL && OF
+	default USB_DWC3
+	help
+	  Actions S500 SoCs with one DesignWare Core USB3 IP
+	  inside
+	  Say 'Y' or 'M' if you have one such device.
+
 config USB_DWC3_QCOM
 	tristate "Qualcomm Platforms"
 	depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
old mode 100644
new mode 100755
index c7076e3..20b6a87
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -35,6 +35,7 @@ endif
 # and allyesconfig builds.
 ##
 
+obj-$(CONFIG_USB_DWC3_ACT)		+= dwc3-actions.o
 obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
 obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
 obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
old mode 100644
new mode 100755
index 1f79708..3136835
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -39,15 +39,111 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/of.h>
 #include <linux/usb/otg.h>
+#include <mach/hardware.h>
+#include <mach/powergate.h>
 
 #include "platform_data.h"
 #include "core.h"
 #include "gadget.h"
 #include "io.h"
 
+#include "usb3_regs.h"
 #include "debug.h"
 
+static char *maximum_speed = "high";
+module_param(maximum_speed, charp, 0);
+MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
+static int dwc3_slew_rate =-1;
+module_param(dwc3_slew_rate, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dwc3_slew_rate, "dwc3_slew_rate");
+static int dwc3_tx_bias=-1;
+module_param(dwc3_tx_bias, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dwc3_tx_bias, "dwc3_tx_bias");
 /* -------------------------------------------------------------------------- */
+#define DWC3_DEVS_POSSIBLE	32
+struct dwc3_port_info {
+	void __iomem *usbecs;
+	void __iomem *devrst;
+	void __iomem *usbpll;
+};
+struct dwc3_actions {
+	struct platform_device	*dwc3;
+	struct device		*dev;
+
+	struct dwc3_port_info port_info;	
+	void __iomem        *base;
+       int 				ic_type;
+};
+enum{
+   IC_ATM7039C = 0,
+   IC_ATM7059A
+};
+static int g_ic_type = IC_ATM7039C;
+
+static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
+
+#if SUPPORT_NOT_RMMOD_USBDRV
+static struct platform_device *pdev_dwc;
+extern  int __dwc3_set_plugstate(struct dwc3	*dwc,int s);
+int dwc3_set_plugstate(int s)
+{
+	struct dwc3	*dwc;
+    
+    	if(pdev_dwc ==NULL){
+		printk("------can't get dwc3 platform device (structure)!!---\n");
+        	return -ENODEV;
+	}            
+            
+    	dwc = platform_get_drvdata(pdev_dwc);
+	 __dwc3_set_plugstate(dwc,s);
+     	return 0;
+}
+EXPORT_SYMBOL_GPL(dwc3_set_plugstate);
+
+void (*dwc3_clk_open)(void );
+void (*dwc3_clk_close)(void );
+ void dwc3_set_usb_clk_ops(void (*clk_open)(void ),void (*clk_close)(void ))
+{
+     dwc3_clk_open = clk_open;
+     dwc3_clk_close = clk_close;
+}
+EXPORT_SYMBOL_GPL(dwc3_set_usb_clk_ops);
+#endif
+
+int dwc3_get_device_id(void)
+{
+	int		id;
+
+again:
+	id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
+	if (id < DWC3_DEVS_POSSIBLE) {
+		int old;
+
+		old = test_and_set_bit(id, dwc3_devs);
+		if (old)
+			goto again;
+	} else {
+		pr_err("dwc3: no space for new device\n");
+		id = -ENOMEM;
+	}
+
+	return id;
+}
+EXPORT_SYMBOL_GPL(dwc3_get_device_id);
+
+void dwc3_put_device_id(int id)
+{
+	int			ret;
+
+	if (id < 0)
+		return;
+
+	ret = test_bit(id, dwc3_devs);
+	WARN(!ret, "dwc3: ID %d not in use\n", id);
+	smp_mb__before_atomic();
+	clear_bit(id, dwc3_devs);
+}
+EXPORT_SYMBOL_GPL(dwc3_put_device_id);
 
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
 {
@@ -63,7 +159,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
  * dwc3_core_soft_reset - Issues core soft reset and PHY reset
  * @dwc: pointer to our context structure
  */
-static int dwc3_core_soft_reset(struct dwc3 *dwc)
+static int dwc3_core_soft_reset(struct dwc3 *dwc,int phy_reset_en)
 {
 	u32		reg;
 	int		ret;
@@ -73,40 +169,55 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
 	reg |= DWC3_GCTL_CORESOFTRESET;
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
-	/* Assert USB3 PHY reset */
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
-	reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
-	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
-
-	/* Assert USB2 PHY reset */
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
-	reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
-	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+	if(phy_reset_en){
+		/* Assert USB3 PHY reset */
+		reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+		reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
+		dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+
+		/* Assert USB2 PHY reset */
+		reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+		reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
+		dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+
+	       if(g_ic_type == IC_ATM7059A){
+			/* port 1 */
+			reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(1));
+			reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
+			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(1), reg);
+		}
 
-	usb_phy_init(dwc->usb2_phy);
-	usb_phy_init(dwc->usb3_phy);
-	ret = phy_init(dwc->usb2_generic_phy);
-	if (ret < 0)
-		return ret;
+		usb_phy_init(dwc->usb2_phy);
+		usb_phy_init(dwc->usb3_phy);
+		ret = phy_init(dwc->usb2_generic_phy);
+		if (ret < 0)
+			return ret;
 
-	ret = phy_init(dwc->usb3_generic_phy);
-	if (ret < 0) {
-		phy_exit(dwc->usb2_generic_phy);
-		return ret;
+		ret = phy_init(dwc->usb3_generic_phy);
+		if (ret < 0) {
+			phy_exit(dwc->usb2_generic_phy);
+			return ret;
+		}
+		mdelay(100);
+
+		/* Clear USB3 PHY reset */
+		reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+		reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
+		dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+
+		/* Clear USB2 PHY reset */
+		reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+		reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
+		dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+
+		 if(g_ic_type == IC_ATM7059A){
+			/* port 1 */
+			reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(1));
+			reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
+			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(1), reg);
+		}
+		mdelay(100);
 	}
-	mdelay(100);
-
-	/* Clear USB3 PHY reset */
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
-	reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
-	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
-
-	/* Clear USB2 PHY reset */
-	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
-	reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
-	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
-
-	mdelay(100);
 
 	/* After PHYs are stable we can take Core out of reset state */
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
@@ -264,7 +375,7 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
  *
  * Returns 0 on success otherwise negative errno.
  */
-static int dwc3_event_buffers_setup(struct dwc3 *dwc)
+int dwc3_event_buffers_setup(struct dwc3 *dwc)
 {
 	struct dwc3_event_buffer	*evt;
 	int				n;
@@ -417,6 +528,208 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
 	parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
 }
 
+static void setphy(unsigned char reg_add, unsigned char value, unsigned char port_num)
+{
+	void __iomem *usb3_usb_vcon=	NULL;
+	volatile unsigned char addr_low;
+	volatile unsigned char addr_high;
+	volatile unsigned int vstate;
+
+	if(g_ic_type == IC_ATM7059A){
+		if (port_num == 0)
+		usb3_usb_vcon = (void __iomem *)IO_ADDRESS((0xB0400000 + 0xCe00));
+		else if (port_num == 1)
+		usb3_usb_vcon = (void __iomem *)IO_ADDRESS((0xB0400000 + 0xCe10));
+		else {
+			printk("port_num must is 0 or 1!!\n");
+			return;
+		}
+	}		
+	else if(g_ic_type == IC_ATM7039C){
+        	usb3_usb_vcon = (void __iomem *)IO_ADDRESS(USB3_USB2_P0_VDCTRL);
+	}
+	addr_low =  reg_add & 0x0f;
+	addr_high =  (reg_add >> 4) & 0x0f;
+
+	vstate = value;
+	vstate = vstate << 8;
+
+	addr_low |= 0x10;
+	writel(vstate | addr_low, usb3_usb_vcon);
+	mb();
+
+	addr_low &= 0x0f; 
+	writel(vstate | addr_low, usb3_usb_vcon);
+	mb();
+
+	addr_low |= 0x10;
+	writel(vstate | addr_low, usb3_usb_vcon);
+	mb();
+
+	addr_high |= 0x10;
+	writel(vstate | addr_high, usb3_usb_vcon);
+	mb();
+
+	addr_high &= 0x0f; 
+	writel(vstate | addr_high, usb3_usb_vcon);
+	mb();
+
+	addr_high |= 0x10;
+	writel(vstate | addr_high, usb3_usb_vcon);  
+	mb();
+	return;
+}
+#define USB3_UMON_FDT_COMPATIBLE_ATM7039C    "actions,atm7039c-usb"
+#define USB3_UMON_FDT_COMPATIBLE_ATM7059TC  "actions,atm7059tc-usb"
+#define USB3_UMON_FDT_COMPATIBLE_ATM7059A    "actions,atm7059a-usb"
+static int dwc3_get_slewrate_config(void)
+{
+	struct device_node *fdt_node;
+	const __be32 *property;
+       int value;
+       
+	fdt_node = of_find_compatible_node(NULL, NULL, USB3_UMON_FDT_COMPATIBLE_ATM7039C);
+	if (NULL == fdt_node) {
+		fdt_node = of_find_compatible_node(NULL, NULL, USB3_UMON_FDT_COMPATIBLE_ATM7059TC);
+		if (NULL == fdt_node) 
+			fdt_node = of_find_compatible_node(NULL, NULL, USB3_UMON_FDT_COMPATIBLE_ATM7059A);
+			if (NULL == fdt_node)
+			{
+				printk("<dwc3>err: no usb3-fdt-compatible\n");
+				return -EINVAL;
+			}
+	}		
+	property = of_get_property(fdt_node, "usb_hs_output_strength", NULL);
+	value = be32_to_cpup(property);
+	return value;
+}
+void dwc3_phy_init(u8 mode, unsigned char port_num)
+{
+	unsigned char val_u8,slew_rate;
+    
+       slew_rate= dwc3_get_slewrate_config();
+       if((port_num!= 0)&&(port_num!= 1)){
+		port_num = 0;
+        }        
+	if(g_ic_type == IC_ATM7039C){
+		setphy(0xe7,0x0b, port_num);
+		udelay(100);
+		setphy(0xe7,0x0f, port_num);
+		udelay(100);
+		setphy(0xe2,0x74, port_num); 
+		udelay(100);
+	}
+	else if(g_ic_type == IC_ATM7059A){
+
+		if(mode == USB_DR_MODE_PERIPHERAL) {
+			printk(" GS705A phy init for dwc3 gadget\n");
+			val_u8 =(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0);//select page1
+			setphy(0xf4, val_u8, port_num);
+			val_u8 =(1<<5) |(1<<4)|(0<<3)|(1<<2)|(1<<0);//negative sample
+			setphy(0xe0, val_u8, port_num);
+            
+			val_u8 =(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0);//select page1
+			setphy(0xf4, val_u8, port_num);
+			val_u8 =(slew_rate<<5) |(0<<4)|(1<<3)|(1<<2)|(3<<0);//slewRate
+			setphy(0xe1, val_u8, port_num);
+            
+			val_u8 =(1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0);//bit[6:5]=select page0
+			setphy(0xf4, val_u8, port_num);
+			val_u8 =(1<<7) |(4<<4)|(1<<3)|(0<<2)|(3<<0); //bit[3]= Enablepowerdown mode
+			setphy(0xe6, val_u8, port_num);
+            
+			val_u8 = (1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0);
+			setphy(0xf4, val_u8, port_num);
+			val_u8 = (7<<4)|(0<<1)|(1<<0);                 //sensitivity lower
+			setphy(0xe7, val_u8, port_num);
+            
+			val_u8 = (1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0);
+			setphy(0xf4, val_u8, port_num);
+			val_u8 = (9<<4)|(7<<0);                               //hstx current lower
+			setphy(0xe4, val_u8, port_num);
+		}
+		else {
+			printk(" GS705A phy init for xhci\n");
+			val_u8 =(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0);//select page1
+			setphy(0xf4, val_u8, port_num);
+			val_u8 =(1<<5) |(1<<4)|(0<<3)|(1<<2)|(1<<0);//negative sample
+			setphy(0xe0, val_u8, port_num);
+            
+			val_u8 =(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0);//select page1
+			setphy(0xf4, val_u8, port_num);
+			if((dwc3_slew_rate >=0) &&(dwc3_slew_rate <= 7))
+				val_u8 =(dwc3_slew_rate<<5) |(0<<4)|(1<<3)|(1<<2)|(3<<0);//slewRate
+			else
+				val_u8 =(3<<5) |(0<<4)|(1<<3)|(1<<2)|(3<<0);//slewRate
+			setphy(0xe1, val_u8, port_num);
+                    
+			val_u8 =(1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0);//bit[6:5]=select page0
+			setphy(0xf4, val_u8, port_num);
+			val_u8 =(1<<7) |(4<<4)|(1<<3)|(0<<2)|(3<<0); //bit[3]= Enablepowerdown mode
+			setphy(0xe6, val_u8, port_num);
+            
+			val_u8 = (1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0);
+			setphy(0xf4, val_u8, port_num);
+			val_u8 = (9<<4)|(0<<1)|(1<<0);                 //sensitivity lower
+			setphy(0xe7, val_u8, port_num);
+            
+			val_u8 =(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0);//select page1
+			setphy(0xf4, val_u8, port_num);
+			val_u8 =(1<<5) |(1<<4)|(0<<3)|(0<<2)|(1<<0);// REG_CAL=0
+			setphy(0xe0, val_u8, port_num);
+            
+			val_u8 = (1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0); // elect page0
+			setphy(0xf4, val_u8, port_num);
+			if((dwc3_tx_bias >=0) &&(dwc3_tx_bias <= 15))
+				val_u8 = (0xf<<4)|(dwc3_tx_bias<<0);                                  //adjust hshd threshold and hstx current
+			else
+				val_u8 = (0xf<<4)|(4<<0);                                  //adjust hshd threshold and hstx current
+			setphy(0xe4, val_u8, port_num);
+
+			val_u8 = (1<<7) |(1<<6) |(1<<5)|(1<<4)|(1<<3)|(1<<2)|(0<<1)|(0<<0);
+			setphy(0xf0, val_u8, port_num);   //disconnect enable
+		}
+
+	}
+
+	return;
+}
+EXPORT_SYMBOL_GPL(dwc3_phy_init);
+
+/*
+ *fix bug:when usb3 bias enable ,reset machine will leak current by gpio 
+ *if call this func will also disable super speed.
+ */
+void disable_bias(void)
+{	
+	struct dwc3 *dwc;
+	u32 reg;
+    
+	dwc = platform_get_drvdata(pdev_dwc);
+	reg = dwc3_readl(dwc->regs, 0xce04);
+	reg |=(1<<27);
+	dwc3_writel(dwc->regs, 0xce04, reg);
+	reg = dwc3_readl(dwc->regs, ANA0F);
+	reg &=~(1<<14);
+	dwc3_writel(dwc->regs, ANA0F, reg);
+
+}
+EXPORT_SYMBOL_GPL(disable_bias);
+
+void enable_bias(void)
+{	
+	struct dwc3 *dwc;
+	u32 reg;
+    
+	dwc = platform_get_drvdata(pdev_dwc);
+	
+	reg = dwc3_readl(dwc->regs, ANA0F);
+	reg |=(1<<14);
+	dwc3_writel(dwc->regs, ANA0F, reg);
+
+}
+EXPORT_SYMBOL_GPL(enable_bias);
+
 /**
  * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
  * @dwc: Pointer to our controller context structure
@@ -425,7 +738,7 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
  * initialized. The PHY interfaces and the PHYs get initialized together with
  * the core in dwc3_core_init.
  */
-static int dwc3_phy_setup(struct dwc3 *dwc)
+int dwc3_phy_setup(struct dwc3 *dwc)
 {
 	u32 reg;
 	int ret;
@@ -530,7 +843,7 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
  *
  * Returns 0 on success otherwise negative errno.
  */
-static int dwc3_core_init(struct dwc3 *dwc)
+int dwc3_core_init(struct dwc3 *dwc,int phy_reset_en)
 {
 	u32			hwparams4 = dwc->hwparams.hwparams4;
 	u32			reg;
@@ -569,9 +882,50 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	if (ret)
 		goto err0;
 
-	ret = dwc3_core_soft_reset(dwc);
-	if (ret)
-		goto err0;
+	if(g_ic_type == IC_ATM7059A){
+		dwc3_writel(dwc->regs, ANA02, 0x6046);
+		dwc3_writel(dwc->regs, ANA0E, 0x2010);
+		dwc3_writel(dwc->regs, ANA0F, 0x8000);
+		dwc3_writel(dwc->regs, REV1, 0x0);
+		dwc3_writel(dwc->regs, PAGE1_REG02, 0x0013);
+		dwc3_writel(dwc->regs, PAGE1_REG06, 0x0004);
+		dwc3_writel(dwc->regs, PAGE1_REG07, 0x22ed);
+		dwc3_writel(dwc->regs, PAGE1_REG08, 0xf802);
+		dwc3_writel(dwc->regs, PAGE1_REG09, 0x3080);
+		dwc3_writel(dwc->regs, PAGE1_REG0B, 0x2030);
+		dwc3_writel(dwc->regs, ANA0F, (1<<14));
+
+		ret = dwc3_core_soft_reset(dwc,phy_reset_en);
+		if (ret)
+			goto err0;
+
+		dwc3_cache_hwparams(dwc);
+            	//====force to high speed====
+		reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+		reg &= ~(DWC3_DCFG_SPEED_MASK);
+		reg |= DWC3_DCFG_HIGHSPEED;
+		dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+	}
+	else if(g_ic_type == IC_ATM7039C){
+		/*
+		 * donot need set this DWC3_BACKDOOR reg,
+		 * this may cause some masstorge device transfer error!!, 
+		 * add by hwliu 2013.07.22 .
+		 */
+		ret = dwc3_core_soft_reset(dwc,phy_reset_en);
+		if (ret)
+			goto err0;
+
+		reg = dwc3_readl(dwc->regs, DWC3_BACKDOOR);
+		reg &= ~DWC3_FLADJ_30MHZ_MASK;	
+		reg |= DWC3_FLADJ_30MHZ(0x20);
+		dwc3_writel(dwc->regs, DWC3_BACKDOOR, reg);
+	}
+	else {
+		ret = dwc3_core_soft_reset(dwc, 0);
+			if (ret)
+				goto err0;
+	}
 
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
@@ -822,6 +1176,10 @@ static int dwc3_probe(struct platform_device *pdev)
 	void __iomem		*regs;
 	void			*mem;
 
+#if SUPPORT_NOT_RMMOD_USBDRV
+	pdev_dwc = pdev;
+#endif
+
 	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
 	if (!mem)
 		return -ENOMEM;
@@ -830,6 +1188,14 @@ static int dwc3_probe(struct platform_device *pdev)
 	dwc->mem = mem;
 	dwc->dev = dev;
 
+       //to get ic type from dwc3-actions.ko,use resource method
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+	if (!res) {
+		dev_err(dev, "missing IRQ\n");
+		return -ENODEV;
+	}
+	g_ic_type = res->flags&0xff;
+
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(dev, "missing IRQ\n");
@@ -982,6 +1348,8 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (ret)
 		goto err0;
 
+	owl_powergate_power_on(OWL_POWERGATE_USB3);
+
 	spin_lock_init(&dwc->lock);
 
 	if (!dev->dma_mask) {
@@ -1009,7 +1377,16 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
 		dwc->dr_mode = USB_DR_MODE_OTG;
 
-	ret = dwc3_core_init(dwc);
+	dwc->dr_mode = USB_DR_MODE_PERIPHERAL;	
+	if(g_ic_type == IC_ATM7039C){
+		dwc3_phy_init(dwc->dr_mode, 0);
+	}
+	else if(g_ic_type == IC_ATM7059A){
+		dwc3_phy_init(dwc->dr_mode, 0);
+		dwc3_phy_init(dwc->dr_mode, 1);
+	}
+
+	ret = dwc3_core_init(dwc,0);
 	if (ret) {
 		dev_err(dev, "failed to initialize core\n");
 		goto err1;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
old mode 100644
new mode 100755
index 78be201..0068cac
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -149,6 +149,11 @@
 #define DWC3_OEVTEN		0xcc0C
 #define DWC3_OSTS		0xcc10
 
+#define DWC3_BACKDOOR   0xcd4c
+
+#define DWC3_FLADJ_30MHZ_MASK	((0x3f) << 10)
+#define DWC3_FLADJ_30MHZ(n)	((n) << 10)
+
 /* Bit fields */
 
 /* Global Configuration Register */
diff --git a/drivers/usb/dwc3/dwc3-actions.c b/drivers/usb/dwc3/dwc3-actions.c
new file mode 100644
index 0000000..86b0432
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-actions.c
@@ -0,0 +1,516 @@
+/**
+ * dwc3-actions.c - actions-semi DWC3 Specific Glue layer
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+#include "core.h"
+#include "usb3_regs.h"
+
+#define  ADFUS_PROC
+static struct resource dwc3_resources[3];
+static u64 dwc3_dma_mask = DMA_BIT_MASK(32);
+static struct platform_device *pdev_dwc_actions;
+extern  void dwc3_set_usb_clk_ops(void (*clk_open)(void ),void (*clk_close)(void ));
+
+#ifdef ADFUS_PROC
+
+#define ADFUS_PROC_FILE_LEN 64
+
+enum probatch_status {
+	PROBATCH_START = 0,
+	PROBATCH_INSTAL_FLASH,
+	PROBATCH_FINISH_INSTALL_FLASH,
+	PROBATCH_WRITE_PHY,
+	PROBATCH_FINISH_WRITE_PHY,
+	PROBATCH_FORMAT,
+	PROBATCH_FINISH_FORMAT,
+	PROBATCH_FINISH,	
+	PROBATCH_FINISH_OK,
+};	
+#endif
+
+enum{
+   IC_ATM7039C = 0,
+   IC_ATM7059A
+};
+
+struct dwc3_port_info {
+	void __iomem *usbecs;
+	void __iomem *devrst;
+	void __iomem *usbpll;
+};
+
+struct dwc3_actions {
+	struct platform_device	*dwc3;
+	struct device		*dev;
+
+	struct dwc3_port_info port_info;	
+	void __iomem        *base;
+       int 				ic_type;
+};
+int dwc3_get_device_id(void);
+void dwc3_put_device_id(int id);
+
+//static void dwc3_clk_init(struct dwc3_actions *dwc3_owl)
+static void dwc3_clk_init(void)
+{
+	u32		reg;
+    	struct dwc3_actions	*dwc3_owl;
+	struct dwc3_port_info *port_info ;
+
+	if(pdev_dwc_actions ==NULL){
+		printk("------can't get dwc3-actions platform device structure!!---\n");
+		return ;
+	}  
+	dwc3_owl = platform_get_drvdata(pdev_dwc_actions);
+	port_info = &dwc3_owl->port_info;
+	printk("\n------------dwc3_clk_init-----ic=%d-----\n",dwc3_owl->ic_type);
+	/*USB3 PLL enable*/
+	reg = readl(port_info->usbpll);
+	if(dwc3_owl->ic_type == IC_ATM7059A){
+	    reg |= (0x7f);
+	}
+	else if(dwc3_owl->ic_type == IC_ATM7039C){
+	    reg |= (0x1f);
+	}
+	writel(reg, port_info->usbpll);
+
+	udelay(1000);
+
+	/*USB3 Cmu Reset */
+	reg = readl(port_info->devrst);
+	reg &= ~(USB3_MOD_RST);
+	writel(reg, port_info->devrst);
+
+	udelay(100);
+	
+	reg = readl(port_info->devrst);
+	reg |= (USB3_MOD_RST);
+	writel(reg, port_info->devrst);
+
+	udelay(100);
+
+ 	if(dwc3_owl->ic_type == IC_ATM7059A){     
+		reg = readl(dwc3_owl->base + DWC3_CMU_DEBUG_LDO);
+		reg |= CMU_BIAS_EN;
+		writel(reg, dwc3_owl->base + DWC3_CMU_DEBUG_LDO);
+		reg = readl(port_info->usbecs );
+		reg |= (1 << USB3_P0_CTL_PLLLDOEN_IC1 )|(/*2*/3 << USB3_P0_CTL_LDOVREFSEL_SHIFT_IC1);
+		writel(reg, port_info->usbecs );
+	}
+	 else if(dwc3_owl->ic_type == IC_ATM7039C){
+		/*PLL1 enable*/
+		reg = readl(dwc3_owl->base + DWC3_CMU_DEBUG_LDO);
+		reg |= CMU_BIAS_EN;
+		writel(reg, dwc3_owl->base + DWC3_CMU_DEBUG_LDO);
+
+		/*PLL2 enable*/
+		reg = (BIST_QINIT(0x3) | EYE_HEIGHT(0x4) | PLL2_LOCK | PLL2_RS(0x2) | 
+				PLL2_ICP(0x1) | CMU_SEL_PREDIV | CMU_DIVX2 | PLL2_DIV(0x17) | 
+				PLL2_POSTDIV(0x3) | PLL2_PU);
+		writel(reg, dwc3_owl->base + DWC3_CMU_PLL2_BISTDEBUG);
+	        reg = readl(port_info->usbecs );
+		reg |= (1 << USB3_P0_CTL_PLLLDOEN )|(2 << USB3_P0_CTL_LDOVREFSEL_SHIFT);
+		writel(reg, port_info->usbecs );
+	}
+     
+	udelay(100);
+	reg = readl(port_info->usbecs);
+	reg &=  ~((0x1 << USB3_P0_CTL_DPPUEN_P0)|(0x1 << USB3_P0_CTL_DMPUEN_P0)); 
+	writel(reg, port_info->usbecs );
+    
+       udelay(1000);
+	return;
+}
+
+//static void dwc3_clk_exit(struct dwc3_actions *dwc3_owl)
+static void dwc3_clk_exit(void)
+{
+	u32		reg;
+    	struct dwc3_actions	*dwc3_owl;
+	struct dwc3_port_info *port_info ;
+
+	if(pdev_dwc_actions ==NULL){
+		printk("------can't get dwc3-actions platform device structure!!---\n");
+		return ;
+	}  
+    	dwc3_owl = platform_get_drvdata(pdev_dwc_actions);
+     	port_info = &dwc3_owl->port_info;
+    
+	printk("\n------------dwc3_clk_exit----------\n");
+	/*USB3 PLL disable*/
+	reg = readl(port_info->usbpll);
+	
+       if(dwc3_owl->ic_type == IC_ATM7059A){
+	    reg &= ~(0x7f);
+       }
+       else if(dwc3_owl->ic_type == IC_ATM7039C){
+	    reg &= ~(0x1f);
+       }
+	writel(reg, port_info->usbpll);
+}
+
+/*---------------------------------------------------------------------------
+ *	proc file entry  for debug
+ *---------------------------------------------------------------------------*/
+#ifdef ADFUS_PROC
+static struct proc_dir_entry *adfus_proc_entry;
+char adfus_proc_path[] = "adfus_proc";
+
+char probatch_phase[ADFUS_PROC_FILE_LEN];
+
+char all_probatch_phase[][ADFUS_PROC_FILE_LEN]=
+{
+	"null",
+	"install_flash",
+	"finish_install_flash",
+	"write_phy",
+	"finish_write_phy",
+	"format",
+	"finish_format",
+	"finish",
+	"finish_ok",
+};
+
+int set_probatch_phase(int id)
+{
+
+	strcpy(probatch_phase, all_probatch_phase[id]);
+	return 0;
+}	
+EXPORT_SYMBOL_GPL(set_probatch_phase);
+
+int is_probatch_phase(int id)
+{
+	int ret;
+	
+	ret = memcmp(probatch_phase, all_probatch_phase[id], strlen(all_probatch_phase[id]));
+	return ret;
+}
+EXPORT_SYMBOL_GPL(is_probatch_phase);
+
+static ssize_t adfus_proc_read(struct file *file, char __user *buffer,
+                   size_t count, loff_t * offset)
+{
+	int len;
+	
+	if(*offset > 0)
+	    return 0;
+	    
+	len = strlen(probatch_phase);
+	if(len > count)
+		len = count;
+		
+    if(copy_to_user(buffer, probatch_phase, len))
+        return -EFAULT;
+    
+    *offset += len;
+	return len;
+}
+
+static ssize_t adfus_proc_write(struct file *file, const char __user *buffer,
+                   size_t count, loff_t * offset)
+{
+	int len;
+	
+	if(*offset > 0)
+	    return 0;
+	if(count > ADFUS_PROC_FILE_LEN)
+		len = ADFUS_PROC_FILE_LEN;
+	else
+		len = count;
+	
+	if (copy_from_user(probatch_phase, buffer, len ))
+		return -EFAULT;
+		
+	probatch_phase[len]=0;
+	
+    *offset += len;
+	return len;
+}
+
+static const struct file_operations __adfus_proc_file_operations =
+{
+    .owner =        THIS_MODULE,
+    .read =         adfus_proc_read,
+    .write =        adfus_proc_write,
+};
+#endif
+
+
+
+static  struct dwc3_actions  atm7039c_data = {
+	.ic_type = IC_ATM7039C,
+
+};
+
+static  struct dwc3_actions  atm7059a_data = {
+	.ic_type = IC_ATM7059A,
+};
+
+static const struct of_device_id  owl_dwc3_actions_of_match[]   = {
+	{.compatible = "actions,atm7039c-usb", .data = &atm7039c_data},
+	{.compatible = "actions,atm7059tc-usb", .data = &atm7059a_data },
+	{.compatible = "actions,atm7059a-usb", .data = &atm7059a_data },
+	{}
+
+};
+MODULE_DEVICE_TABLE(of, owl_dwc3_actions_of_match);
+
+static int  dwc3_actions_probe(struct platform_device *pdev)
+{
+	struct platform_device	*dwc3;
+	struct resource		*res;
+	struct device       *dev = &pdev->dev;
+	struct dwc3_actions	*dwc3_owl;
+    	const struct of_device_id *id;
+	void __iomem        *base;
+	int			devid = 0;
+	int			ret = -ENOMEM;
+       
+	pdev_dwc_actions = pdev;//record this platform_device for later use
+	id = of_match_device(owl_dwc3_actions_of_match, &pdev->dev);
+	if(id ==NULL)
+	{
+		printk("<dwc3_actions>err: no config !!!\n");
+		return -EINVAL;
+	}
+	dwc3_owl =(struct dwc3_actions	*) id->data;
+      
+	(pdev->dev).dma_mask = &dwc3_dma_mask;
+	(pdev->dev).coherent_dma_mask	= DMA_BIT_MASK(32);
+	//dwc3_5202 = devm_kzalloc(dev,sizeof(*dwc3_5202), GFP_KERNEL);
+	//if (!dwc3_5202) {
+	//	dev_err(&pdev->dev, "not enough memory\n");
+	//	goto err1;
+	//}
+    platform_set_drvdata(pdev, dwc3_owl);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing memory base resource\n");
+		return -EINVAL;
+	}
+	memcpy(&dwc3_resources[0], res, sizeof(*res));
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "missing IRQ base resource\n");
+		return -EINVAL;
+	}
+	memcpy(&dwc3_resources[1], res, sizeof(*res));
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(dev, "missing memory base resource\n");
+		return -EINVAL;
+	}
+
+	res = devm_request_mem_region(dev, res->start,resource_size(res),
+			dev_name(dev));
+	if (!res) {
+		dev_err(dev, "can't request mem region\n");
+		return -ENOMEM;
+	}
+
+	base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!base) {
+		dev_err(dev, "ioremap failed\n");
+		return -ENOMEM;
+	}
+	
+	dwc3_owl->port_info.devrst = (void __iomem *)IO_ADDRESS(CMU_DEVRST1);
+	dwc3_owl->port_info.usbecs = (void __iomem *)IO_ADDRESS(USB3_P0_CTL);
+	dwc3_owl->port_info.usbpll = (void __iomem *)IO_ADDRESS(CMU_USBPLL);
+
+	devid = dwc3_get_device_id();
+	if (devid < 0)	
+		return -ENODEV;
+		
+
+	dwc3 = platform_device_alloc("dwc3", devid);
+	if (!dwc3) {
+		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
+		goto err1;
+	}
+
+	dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
+
+	dwc3->dev.parent = &pdev->dev;
+	dwc3->dev.dma_mask = pdev->dev.dma_mask;
+	dwc3->dev.dma_parms = pdev->dev.dma_parms;
+	dwc3_owl->dwc3	= dwc3;
+	dwc3_owl->dev	= &pdev->dev;
+	dwc3_owl->base	= base;
+
+    	dwc3_set_usb_clk_ops(dwc3_clk_init,dwc3_clk_exit);
+	dwc3_clk_init();
+       //to transfor ic type to dwc3.ko,use resource method
+       dwc3_resources[2] = dwc3_resources[1];
+       dwc3_resources[2].flags = (IORESOURCE_REG|(dwc3_owl->ic_type));
+	ret = platform_device_add_resources(dwc3, dwc3_resources, 3);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
+		goto err2;
+	}
+
+	ret = platform_device_add(dwc3);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register dwc3 device\n");
+		goto err2;
+	}
+#ifdef ADFUS_PROC
+	adfus_proc_entry = proc_create(adfus_proc_path, 0, NULL, &__adfus_proc_file_operations);
+	if (adfus_proc_entry) {
+		/* proc op */
+		strcpy(probatch_phase, all_probatch_phase[0]);		
+	} else {
+		/* proc op */
+		printk("adfus :can not create proc file\n");
+	}
+#endif
+	return 0;
+	
+err2:
+	platform_device_put(dwc3);
+	dwc3_clk_exit();
+err1:
+	dwc3_put_device_id(devid);
+	return ret;
+}
+#if 0
+#ifdef CONFIG_PM
+static int dwc3_actions_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	int	irq;
+	struct dwc3_actions	*dwc3_owl = platform_get_drvdata(pdev);
+	irq = platform_get_irq(dwc3_owl->dwc3, 0);
+	disable_irq(irq);
+	//dwc3_clk_exit(dwc3_5202);
+    
+	return 0;
+}
+
+static int dwc3_actions_resume(struct platform_device *pdev)
+{
+	int	irq;
+	struct dwc3_actions	*dwc3_owl = platform_get_drvdata(pdev);
+	irq = platform_get_irq(dwc3_owl->dwc3, 0);
+	//dwc3_clk_init(dwc3_owl);
+	enable_irq(irq);
+
+	return 0;
+}
+#else
+#define	dwc3_actions_suspend	NULL
+#define	dwc3_actions_resume		NULL
+#endif
+#endif
+static int  dwc3_actions_remove(struct platform_device *pdev)
+{
+	struct dwc3_actions	*dwc3_owl = platform_get_drvdata(pdev);
+#ifdef ADFUS_PROC
+	if (adfus_proc_entry)
+		remove_proc_entry(adfus_proc_path, NULL);
+#endif
+	dwc3_clk_exit();
+	platform_device_unregister(dwc3_owl->dwc3);
+	dwc3_put_device_id(dwc3_owl->dwc3->id);
+
+	return 0;
+}
+#if 0
+static void dwc3_actions_release(struct device * dev)
+{
+	return ;
+}
+
+
+static struct resource dwc3_resources[] = {
+	[0] = {
+		.start	= USB3_REGISTER_BASE,
+		.end	= USB3_REGISTER_BASE + USB3_ACTIONS_START - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= OWL_IRQ_USB3,
+		.end	= OWL_IRQ_USB3,
+		.flags	= IORESOURCE_IRQ,
+	},	
+};
+
+static struct resource actions_resources[] = {
+	[0] = {
+		.start	= USB3_REGISTER_BASE + USB3_ACTIONS_START,
+		.end	= USB3_REGISTER_BASE + USB3_ACTIONS_END,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static u64 dwc3_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device dwc3_actions_device = {
+	.name       = "actions-dwc3",
+	.id     = 1,
+	.dev	= {
+		.dma_mask		= &dwc3_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),	
+		.release = dwc3_actions_release,
+	},
+	.resource	= actions_resources,
+	.num_resources	= ARRAY_SIZE(actions_resources),    
+};
+
+#endif
+static struct platform_driver dwc3_actions_driver = {
+	.probe		= dwc3_actions_probe,
+	.remove		= dwc3_actions_remove,
+	//.suspend	= dwc3_actions_suspend,
+	//.resume		= dwc3_actions_resume,
+	.driver		= {
+		.name	= "actions-dwc3",
+					.of_match_table = owl_dwc3_actions_of_match,
+	},
+};
+
+static int __init  dwc3_actions_init(void)
+{
+	//platform_device_register(&dwc3_actions_device);
+	return platform_driver_register(&dwc3_actions_driver);
+}
+module_init(dwc3_actions_init);
+
+static void __exit dwc3_actions_exit(void)
+{
+	platform_driver_unregister(&dwc3_actions_driver);
+	//platform_device_unregister(&dwc3_actions_device);
+}
+module_exit(dwc3_actions_exit);
+
+//module_platform_driver(dwc3_actions_driver);
+
+MODULE_ALIAS("platform:actions-dwc3");
+MODULE_AUTHOR("wanlong <wanlong at actions-semi.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DesignWare USB3 actions Glue Layer");
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
old mode 100644
new mode 100755
index 00f2c45..ffd2eb3
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -104,7 +104,13 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
 
 	return 0;
 }
+static int no_delay_status = 0;
+void set_no_delay_status(int flag)
+{
+	no_delay_status = flag;
+}
 
+EXPORT_SYMBOL(set_no_delay_status);
 static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 		struct dwc3_request *req)
 {
@@ -153,7 +159,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 		direction = !dwc->ep0_expect_in;
 		dwc->delayed_status = false;
 		usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
-
+		no_delay_status = 0;
 		if (dwc->ep0state == EP0_STATUS_PHASE)
 			__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
 		else
@@ -162,8 +168,11 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 
 		return 0;
 	}
-
-	/*
+	 else {
+		if(no_delay_status == 1)
+			dev_dbg(dwc->dev, "---- dwc3_ep0_inspect_setup is behind usb_composite_setup_continue !!\n");
+	}
+    /*
 	 * Unfortunately we have uncovered a limitation wrt the Data Phase.
 	 *
 	 * Section 9.4 says we can wait for the XferNotReady(DATA) event to
@@ -1062,11 +1071,19 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 		dwc->ep0state = EP0_STATUS_PHASE;
 
 		if (dwc->delayed_status) {
-			WARN_ON_ONCE(event->endpoint_number != 1);
-			dwc3_trace(trace_dwc3_ep0, "Delayed Status");
-			return;
+			//WARN_ON_ONCE(event->endpoint_number != 1);
+			//dwc3_trace(trace_dwc3_ep0, "Delayed Status");
+			//return;
+			if (no_delay_status == 0) {
+				WARN_ON_ONCE(event->endpoint_number != 1);
+				dwc3_trace(trace_dwc3_ep0, "Delayed Status");
+				return;
+			}
 		}
-
+		if(no_delay_status == 1) {
+			no_delay_status = 0;
+			dwc->delayed_status = false;
+		} 
 		dwc3_ep0_do_control_status(dwc, event);
 	}
 }
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
old mode 100644
new mode 100755
index a5e1b8b..59e277c
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -26,15 +26,84 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/dma-mapping.h>
+#include <linux/kallsyms.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <mach/bootdev.h>
 
 #include "debug.h"
 #include "core.h"
 #include "gadget.h"
 #include "io.h"
 
+#if SUPPORT_NOT_RMMOD_USBDRV
+#include "hotplug_handle.c"
+#endif
+
+
+#ifdef USB_CHARGE_DETECT
+typedef void (*FUNC)(int);
+#define  USB_CONNECT_TO_PC				1
+#define  USB_CONNECT_TO_ADAPTOR		2
+
+u32 reset_interrupt_occured =0;
+struct delayed_work dwc3_work;
+FUNC dwc3_set_usb_plugin_type;
+FUNC dwc3_set_usb_plugin_type_monitor;
+extern int owl_get_boot_mode(void);
+
+static void dwc3_charging_monitor(struct work_struct *work)
+{
+	/*0: not occured, connected adaptor. 1: occured , connected pc*/
+	if(!reset_interrupt_occured) {
+		if(owl_get_boot_mode() != OWL_BOOT_MODE_UPGRADE) {
+            		printk("%s %d set adaptor mode!\n", __func__, __LINE__);
+			if(dwc3_set_usb_plugin_type)	
+				dwc3_set_usb_plugin_type(USB_CONNECT_TO_ADAPTOR);
+			dwc3_set_usb_plugin_type_monitor =
+				(FUNC )kallsyms_lookup_name("monitor_set_usb_plugin_type");
+			if(dwc3_set_usb_plugin_type_monitor)	
+				dwc3_set_usb_plugin_type_monitor(USB_CONNECT_TO_ADAPTOR);	
+		}		
+	}
+}
+
+static void usb_charge_detect_init(void)
+{
+	reset_interrupt_occured = 0;
+	INIT_DELAYED_WORK(&dwc3_work, dwc3_charging_monitor);
+	dwc3_set_usb_plugin_type = (FUNC )kallsyms_lookup_name("atc260x_set_usb_plugin_type");
+}
+
+static void start_usb_status_delaywork(void)
+{
+	/*cancel the delay work & reset the interrupt counter*/
+	cancel_delayed_work_sync(&dwc3_work);
+	//reset_interrupt_occured = 0;
+	/*10s*/ 
+	if(owl_get_boot_mode() != OWL_BOOT_MODE_UPGRADE)
+		schedule_delayed_work(&dwc3_work, msecs_to_jiffies(15000));
+}
+
+static void set_connect_type_to_pc_mode(void)
+{
+	reset_interrupt_occured ++;
+	if(reset_interrupt_occured == 1) {
+		if(owl_get_boot_mode() != OWL_BOOT_MODE_UPGRADE) {
+			if(dwc3_set_usb_plugin_type)	
+				dwc3_set_usb_plugin_type(USB_CONNECT_TO_PC);
+			dwc3_set_usb_plugin_type_monitor =
+				(FUNC )kallsyms_lookup_name("monitor_set_usb_plugin_type");
+			if(dwc3_set_usb_plugin_type_monitor)	
+				dwc3_set_usb_plugin_type_monitor(USB_CONNECT_TO_PC);
+		}
+	}
+}
+
+
+#endif
+
 /**
  * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
  * @dwc: pointer to our context structure
@@ -1526,9 +1595,19 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 	is_on = !!is_on;
 
 	spin_lock_irqsave(&dwc->lock, flags);
+#if SUPPORT_NOT_RMMOD_USBDRV
+	if(!dwc3_gadget_is_plugin()) {
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return 0;
+	}
+#endif
 	ret = dwc3_gadget_run_stop(dwc, is_on, false);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
+#ifdef USB_CHARGE_DETECT    
+	start_usb_status_delaywork();
+#endif
+
 	return ret;
 }
 
@@ -1816,6 +1895,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 	unsigned int		count;
 	unsigned int		s_pkt = 0;
 	unsigned int		trb_status;
+	unsigned int		loop;
 
 	trace_dwc3_complete_trb(dep, trb);
 
@@ -1832,7 +1912,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 	if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO))
 		trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
 
-	if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
+	if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) {
 		/*
 		 * We continue despite the error. There is not much we
 		 * can do. If we don't clean it up we loop forever. If
@@ -1843,6 +1923,17 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
 		 */
 		dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n",
 				dep->name, trb);
+		loop = 500000;  /* 500ms */
+		while(trb->ctrl & DWC3_TRB_CTRL_HWO) {
+			loop --;
+			if(loop == 0) {
+				dev_err(dwc->dev, "%s's TRB (%p) after 500000 us, still owned by HW\n",
+				dep->name, req->trb);
+				break;
+			}
+			udelay(1);
+		}
+	}
 
 	count = trb->size & DWC3_TRB_SIZE_MASK;
 
@@ -2234,6 +2325,34 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 	usb_gadget_set_state(&dwc->gadget, USB_STATE_NOTATTACHED);
 }
 
+static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend)
+{
+	u32			reg;
+
+	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+
+	if (suspend)
+		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+	else
+		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+
+	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+}
+
+static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend)
+{
+	u32			reg;
+
+	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+
+	if (suspend)
+		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+	else
+		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
+	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+}
+
 static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
 	u32			reg;
@@ -2283,6 +2402,10 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg &= ~(DWC3_DCFG_DEVADDR_MASK);
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+#ifdef USB_CHARGE_DETECT    
+	set_connect_type_to_pc_mode();
+#endif
 }
 
 static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed)
@@ -2637,9 +2760,23 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 
 	while (left > 0) {
 		union dwc3_event event;
+		u32 loop;
 
 		event.raw = *(u32 *) (evt->buf + evt->lpos);
-
+		if(event.raw==0 ){
+			loop = 500000;  /* 500ms */
+			while(event.raw == 0){
+				dev_dbg(dwc->dev, "wait event sync\n");
+				loop --;
+				if(loop == 0){
+					dev_err(dwc->dev, "after wait 500ms, process event buf error\n");
+					break;
+				}
+				udelay(1);
+				event.raw = *(u32 *) (evt->buf + evt->lpos);
+			}
+			printk("\n--wait eventbuffer use %d us--new=0x%x--pos=%d--\n",500000 - loop,*(u32 *) (evt->buf + evt->lpos),evt->lpos);
+		}
 		dwc3_process_event_entry(dwc, &event);
 
 		/*
@@ -2651,6 +2788,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 		 * boundary so I worry about that once we try to handle
 		 * that.
 		 */
+		*(u32 *) (evt->buf + evt->lpos) = 0;/*   just to avoid bus reset bug*/
 		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
 		left -= 4;
 
@@ -2773,6 +2911,11 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	}
 
 	dwc->gadget.ops			= &dwc3_gadget_ops;
+#ifdef CONFIG_USB_GADGET_SUPERSPEED
+	dwc->gadget.max_speed	= USB_SPEED_SUPER,
+#else
+	dwc->gadget.max_speed	= USB_SPEED_HIGH,
+#endif
 	dwc->gadget.speed		= USB_SPEED_UNKNOWN;
 	dwc->gadget.sg_supported	= true;
 	dwc->gadget.name		= "dwc3-gadget";
@@ -2821,6 +2964,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 		goto err4;
 	}
 
+#ifdef USB_CHARGE_DETECT	
+	usb_charge_detect_init();
+#endif
+
 	return 0;
 
 err4:
@@ -2861,6 +3008,10 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 			dwc->ctrl_req, dwc->ctrl_req_addr);
+
+#ifdef USB_CHARGE_DETECT	    
+	cancel_delayed_work_sync(&dwc3_work);
+#endif
 }
 
 int dwc3_gadget_suspend(struct dwc3 *dwc)
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
old mode 100644
new mode 100755
index 18ae3ea..09f91ff
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -56,6 +56,20 @@ struct dwc3;
 /* DEPXFERCFG parameter 0 */
 #define DWC3_DEPXFERCFG_NUM_XFER_RES(n)	((n) & 0xffff)
 
+#define  SUPPORT_NOT_RMMOD_USBDRV 1
+#define USB_CHARGE_DETECT 
+
+enum plugstate{
+	PLUGSTATE_A_OUT=0,
+	PLUGSTATE_B_OUT,
+	PLUGSTATE_A_IN,
+	PLUGSTATE_B_IN,
+	PLUGSTATE_A_SUSPEND,
+	PLUGSTATE_A_RESUME,	
+	PLUGSTATE_B_SUSPEND,
+	PLUGSTATE_B_RESUME,	
+};
+     
 /* -------------------------------------------------------------------------- */
 
 #define to_dwc3_request(r)	(container_of(r, struct dwc3_request, request))
diff --git a/drivers/usb/dwc3/hotplug_handle.c b/drivers/usb/dwc3/hotplug_handle.c
new file mode 100644
index 0000000..6ca788d
--- /dev/null
+++ b/drivers/usb/dwc3/hotplug_handle.c
@@ -0,0 +1,237 @@
+/**
+ * hotplug_handle.c - actions-semi DWC3 Specific Glue layer
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/kallsyms.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <mach/hardware.h>
+#include <mach/powergate.h>
+#include "core.h"
+#include "gadget.h"
+#include "io.h"
+#if SUPPORT_NOT_RMMOD_USBDRV
+extern int dwc3_core_init(struct dwc3 *dwc,int phy_reset_en);
+extern  int dwc3_event_buffers_setup(struct dwc3 *dwc);
+extern void dwc3_phy_init(u8 mode, unsigned char port_num);
+extern void (*dwc3_clk_open)(void );
+extern void (*dwc3_clk_close)(void );
+int dwc3_gadget_suspend(struct dwc3 *dwc);
+int dwc3_gadget_resume(struct dwc3 *dwc);
+static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
+static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend);
+static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend);
+static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
+extern u32 reset_interrupt_occured ;
+extern void disable_bias(void);
+
+static int gadget_is_plugin =1;
+static int dwc3_gadget_is_plugin(void)
+{
+	return gadget_is_plugin;
+}
+
+
+static int dwc3_gadget_plugout(struct dwc3 *dwc,int s)
+{
+       int cnt =500;
+       int			irq;
+       unsigned long	flags;
+       
+       spin_lock_irqsave(&dwc->lock, flags);
+       gadget_is_plugin =0;
+       //--step1------Waits until the Core Idle bit in DSTS is set------
+       while(--cnt>0)
+       {
+           if(dwc3_readl(dwc->regs, DWC3_DSTS)&DWC3_DSTS_COREIDLE)
+               break;
+           udelay(100);
+       }
+       //-----step2--------stop core  ------------------------------------   
+       if(s==PLUGSTATE_B_OUT)
+		dwc->gadget_driver->disconnect(&dwc->gadget);
+       dwc3_gadget_run_stop(dwc, 0, 0);
+       dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);   
+       dwc->gadget.speed = USB_SPEED_UNKNOWN;
+
+       //-----step3--------disable ep0  ------------------------------------ 
+	dwc3_gadget_suspend(dwc);
+       
+       spin_unlock_irqrestore(&dwc->lock, flags);  
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	free_irq(irq, dwc);
+
+	return 0;
+}
+
+static int dwc3_gadget_plugin(struct dwc3 *dwc)
+{
+	int			ret;
+       u32 reg;
+       int			irq;
+       unsigned long	flags;
+       
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+		IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+				irq, ret);
+		return -EAGAIN ;
+	}
+       spin_lock_irqsave(&dwc->lock, flags);
+       
+#ifdef USB_CHARGE_DETECT       
+       reset_interrupt_occured = 0;/*reset this flag every time plug in */
+#endif
+       //-----step1--------do dwc3_gadget_exit() things --------------
+       reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+	reg |= DWC3_DCFG_LPM_CAP;
+	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+	/* Enable all but Start and End of Frame IRQs */
+	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
+			DWC3_DEVTEN_EVNTOVERFLOWEN |
+			DWC3_DEVTEN_CMDCMPLTEN |
+			DWC3_DEVTEN_ERRTICERREN |
+			DWC3_DEVTEN_WKUPEVTEN |
+			DWC3_DEVTEN_ULSTCNGEN |
+			DWC3_DEVTEN_CONNECTDONEEN |
+			DWC3_DEVTEN_USBRSTEN |
+			DWC3_DEVTEN_DISCONNEVTEN);
+	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
+
+	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
+	if (dwc->revision >= DWC3_REVISION_194A) {
+		reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+		reg |= DWC3_DCFG_LPM_CAP;
+		dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+		reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
+
+		/* TODO: This should be configurable */
+		reg |= DWC3_DCTL_HIRD_THRES(28);
+
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+		dwc3_gadget_usb2_phy_suspend(dwc, false);
+		dwc3_gadget_usb3_phy_suspend(dwc, false);
+	}
+    
+      //-----step2--------set core run ------------------------------------      
+       dwc3_gadget_run_stop(dwc, 1, 0);
+      
+       //-----step3-------enable&config ep0 -----------------------------
+       reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+	reg &= ~(DWC3_DCFG_SPEED_MASK);
+	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+	dwc3_gadget_resume(dwc);
+    
+	dwc->gadget.speed = USB_SPEED_UNKNOWN;
+	gadget_is_plugin =1;
+    
+       spin_unlock_irqrestore(&dwc->lock, flags);  
+	return 0;
+}
+int dwc3_plug_out(struct dwc3	*dwc,int s)
+{
+	if(((s == PLUGSTATE_B_OUT)||(s == PLUGSTATE_B_SUSPEND))&&(dwc->gadget_driver ==NULL))
+		return 0;
+	if((s == PLUGSTATE_B_OUT)||(s == PLUGSTATE_B_SUSPEND)){
+		dwc3_gadget_plugout(dwc,s);
+	}
+
+	if(s == PLUGSTATE_A_OUT){
+		dwc3_host_exit(dwc);
+	}
+	return 0;
+}
+
+ int dwc3_plug_in(struct dwc3	*dwc,int s)
+{
+	int ret=0;
+
+
+	if((s == PLUGSTATE_B_IN)&&(dwc->gadget_driver == NULL))
+		return 0;
+    
+       owl_powergate_power_on(OWL_POWERGATE_USB3);
+	ret = dwc3_core_init(dwc,1);
+	if (ret) {
+		dev_err(dwc->dev, "failed to initialize core\n");
+		return ret;
+	}
+	dwc3_event_buffers_setup(dwc);
+	dwc3_phy_init(dwc->dr_mode,0);
+	dwc3_phy_init(dwc->dr_mode,1);
+	if(s == PLUGSTATE_A_IN){
+		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
+        	ret = dwc3_host_init(dwc);
+		if (ret) {
+			return 0;
+		}
+	}
+	else if(s == PLUGSTATE_B_IN){
+		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);    
+		ret =dwc3_gadget_plugin(dwc);
+		disable_bias();
+	}     
+	pm_runtime_disable(dwc->dev);
+	pm_runtime_set_active(dwc->dev);
+	pm_runtime_enable(dwc->dev);
+
+	return ret;	
+    
+}
+
+/*
+*plugstate:
+*	0:	idle, nothing plugin or connect
+*	1:	host, A_IN,  plug in udisk via otg wire
+*	2:	device, B_IN, connect to pc
+*/
+int __dwc3_set_plugstate(struct dwc3	*dwc,int s)
+{
+   	if(dwc ==NULL){
+		printk("---dwc3  device (structure) not exist!!---\n");
+        	return -ENODEV;
+	}        
+	if((s==PLUGSTATE_A_OUT)||(s==PLUGSTATE_B_OUT)||(s==PLUGSTATE_B_SUSPEND)){    
+		printk("\n----udc_set_plugstate--PLUGSTATE_OUT--\n");
+        	dwc3_plug_out(dwc,s);
+		if(owl_powergate_is_powered(OWL_POWERGATE_USB3))
+			owl_powergate_power_off(OWL_POWERGATE_USB3);    
+		if(dwc3_clk_close)
+			dwc3_clk_close();
+		
+	}
+	else if((s==PLUGSTATE_A_IN)||(s==PLUGSTATE_B_IN)){
+		printk("\n----udc_set_plugstate--PLUGSTATE_IN-%d--\n",s);
+		if(dwc3_clk_open)
+			dwc3_clk_open();
+		dwc3_plug_in(dwc,s);
+	}
+	return 0;
+}
+
+
+#endif
+
diff --git a/drivers/usb/dwc3/irqs.h b/drivers/usb/dwc3/irqs.h
new file mode 100644
index 0000000..2aa31cb
--- /dev/null
+++ b/drivers/usb/dwc3/irqs.h
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-owl/include/mach/irqs.h
+ *
+ * IRQ definitions
+ *
+ * Copyright 2012 Actions Semi Inc.
+ * Author: Actions Semi, 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;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define IRQ_LOCALTIMER              (29)
+#define IRQ_LOCALWDT                (30)
+
+#define OWL_IRQ_OFFSET             (32)
+#define OWL_IRQ(x)                 ((x) + OWL_IRQ_OFFSET)
+
+#define OWL_IRQ_ETHERNET           OWL_IRQ(0)
+#define OWL_IRQ_DE                 OWL_IRQ(1)
+#define OWL_IRQ_IMX                OWL_IRQ(2)
+#define OWL_IRQ_GPU                OWL_IRQ(3)
+#define OWL_IRQ_PC0                OWL_IRQ(4)
+#define OWL_IRQ_PC1                OWL_IRQ(5)
+#define OWL_IRQ_PC2                OWL_IRQ(6)
+#define OWL_IRQ_PC3                OWL_IRQ(7)
+#define OWL_IRQ_RESERVED0          OWL_IRQ(8)
+#define OWL_IRQ_RESERVED1          OWL_IRQ(9)
+#define OWL_IRQ_TIMER0             OWL_IRQ(10)
+#define OWL_IRQ_TIMER1             OWL_IRQ(11)
+#define OWL_IRQ_BISP               OWL_IRQ(12)
+#define OWL_IRQ_SIRQ0              OWL_IRQ(13)
+#define OWL_IRQ_SIRQ1              OWL_IRQ(14)
+#define OWL_IRQ_SIRQ2              OWL_IRQ(15)
+#define OWL_IRQ_GPIOF              OWL_IRQ(16)
+#define OWL_IRQ_PCM0               OWL_IRQ(17)
+#define OWL_IRQ_PCM1               OWL_IRQ(18)
+#define OWL_IRQ_SPI0               OWL_IRQ(19)
+#define OWL_IRQ_SPI1               OWL_IRQ(20)
+#define OWL_IRQ_SPI2               OWL_IRQ(21)
+#define OWL_IRQ_SPI3               OWL_IRQ(22)
+#define OWL_IRQ_USB3               OWL_IRQ(23)
+#define OWL_IRQ_USB2H0             OWL_IRQ(24)
+#define OWL_IRQ_I2C0               OWL_IRQ(25)
+#define OWL_IRQ_I2C1               OWL_IRQ(26)
+#define OWL_IRQ_I2C2               OWL_IRQ(27)
+#define OWL_IRQ_I2C3               OWL_IRQ(28)
+#define OWL_IRQ_UART0              OWL_IRQ(29)
+#define OWL_IRQ_UART1              OWL_IRQ(30)
+#define OWL_IRQ_UART2              OWL_IRQ(31)
+#define OWL_IRQ_UART3              OWL_IRQ(32)
+#define OWL_IRQ_UART4              OWL_IRQ(33)
+#define OWL_IRQ_UART5              OWL_IRQ(34)
+#define OWL_IRQ_UART6              OWL_IRQ(35)
+#define OWL_IRQ_GPIOA              OWL_IRQ(36)
+#define OWL_IRQ_GPIOB              OWL_IRQ(37)
+#define OWL_IRQ_GPIOC              OWL_IRQ(38)
+#define OWL_IRQ_GPIOD              OWL_IRQ(39)
+#define OWL_IRQ_GPIOE              OWL_IRQ(40)
+#define OWL_IRQ_NAND0              OWL_IRQ(41)
+#define OWL_IRQ_SD0                OWL_IRQ(42)
+#define OWL_IRQ_SD1                OWL_IRQ(43)
+#define OWL_IRQ_SD2                OWL_IRQ(44)
+#define OWL_IRQ_LCD                OWL_IRQ(45)
+#define OWL_IRQ_HDMI               OWL_IRQ(46)
+#define OWL_IRQ_USB2H1             OWL_IRQ(47)
+#define OWL_IRQ_AUDIO_INOUT        OWL_IRQ(48)
+#define OWL_IRQ_VCE                OWL_IRQ(49)
+#define OWL_IRQ_VDE                OWL_IRQ(50)
+#define OWL_IRQ_DSI                OWL_IRQ(51)
+#define OWL_IRQ_CSI0               OWL_IRQ(52)
+#define OWL_IRQ_NAND1              OWL_IRQ(53)
+#define OWL_IRQ_DCU_DEBUG          OWL_IRQ(54)
+#define OWL_IRQ_L2                 OWL_IRQ(55)
+#define OWL_IRQ_HDCP2TX            OWL_IRQ(56)
+#define OWL_IRQ_DMA0               OWL_IRQ(57)
+#define OWL_IRQ_DMA1               OWL_IRQ(58)
+#define OWL_IRQ_DMA2               OWL_IRQ(59)
+#define OWL_IRQ_DMA3               OWL_IRQ(60)
+#define OWL_IRQ_CSI1               OWL_IRQ(61)
+#define OWL_IRQ_SD3                OWL_IRQ(62)
+#define OWL_IRQ_SECURE_TIME2       OWL_IRQ(63)
+#define OWL_IRQ_SECURE_TIME3       OWL_IRQ(64)
+#define OWL_IRQ_EDP                OWL_IRQ(65)
+#define OWL_IRQ_HDE                OWL_IRQ(66)
+#define OWL_IRQ_SE                 OWL_IRQ(67)
+#define OWL_IRQ_DCU_CH0            OWL_IRQ(68)
+#define OWL_IRQ_DCU_CH1            OWL_IRQ(69)
+
+/* Set the default NR_IRQS */
+#define NR_OWL_IRQS                (OWL_IRQ(69) + 1)
+
+/* virtual IRQs: external speical IRQs */
+#define OWL_EXT_IRQ_SIRQ_BASE               (NR_OWL_IRQS)
+#define OWL_EXT_IRQ_SIRQ0                   (OWL_EXT_IRQ_SIRQ_BASE + 0)
+#define OWL_EXT_IRQ_SIRQ1                   (OWL_EXT_IRQ_SIRQ_BASE + 1)
+#define OWL_EXT_IRQ_SIRQ2                   (OWL_EXT_IRQ_SIRQ_BASE + 2)
+#define NR_OWL_SIRQ                (3)
+
+/* virtual IRQs: GPIO */
+#define OWL_EXT_IRQ_GPIOA_BASE              (OWL_EXT_IRQ_SIRQ_BASE + NR_OWL_SIRQ)
+#define OWL_EXT_IRQ_GPIOA(x)                (OWL_EXT_IRQ_GPIOA_BASE + (x))
+#define OWL_EXT_IRQ_GPIOB_BASE              (OWL_EXT_IRQ_GPIOA(31) + 1)
+#define OWL_EXT_IRQ_GPIOB(x)                (OWL_EXT_IRQ_GPIOB_BASE + (x))
+#define OWL_EXT_IRQ_GPIOC_BASE              (OWL_EXT_IRQ_GPIOB(31) + 1)
+#define OWL_EXT_IRQ_GPIOC(x)                (OWL_EXT_IRQ_GPIOC_BASE + (x))
+#define OWL_EXT_IRQ_GPIOD_BASE              (OWL_EXT_IRQ_GPIOC(31) + 1)
+#define OWL_EXT_IRQ_GPIOD(x)                (OWL_EXT_IRQ_GPIOD_BASE + (x))
+
+#define NR_OWL_EXT_GPIO_INT            (3 * 32 + 22)   /* for ATM7029 */
+
+#define OWL_EXT_GPIO_TO_IRQ(gpio)      ((gpio) + OWL_EXT_IRQ_GPIOA_BASE)
+#define OWL_EXT_IRQ_TO_GPIO(irq)       ((irq) - OWL_EXT_IRQ_GPIOA_BASE)
+
+/* virtual IRQs: ATC260x */
+#define IRQ_ATC260X_BASE             (OWL_EXT_IRQ_GPIOA_BASE + NR_OWL_EXT_GPIO_INT)
+/* reserved 16 interrupt sources for ATC260x */
+#define IRQ_ATC260X_MAX_NUM          16
+
+#define NR_IRQS                     (IRQ_ATC260X_BASE + IRQ_ATC260X_MAX_NUM)
+
+#endif  /* __ASM_ARCH_IRQS_H */
diff --git a/drivers/usb/dwc3/usb3_regs.h b/drivers/usb/dwc3/usb3_regs.h
new file mode 100644
index 0000000..9abb741
--- /dev/null
+++ b/drivers/usb/dwc3/usb3_regs.h
@@ -0,0 +1,136 @@
+#ifndef  __USB3_REGS_H__
+#define  __USB3_REGS_H__
+
+//--------------USB3_Register-------------------------------------------//
+//--------------Register Address---------------------------------------//
+#define ANA00 (0+0xCD00)
+#define ANA01 (0+0xCD04)
+#define ANA02 (0+0xCD08)
+#define ANA03 (0+0xCD0C)
+#define ANA04 (0+0xCD10)
+
+#define ANA05 (0+0xCD14)
+#define ANA06 (0+0xCD18)
+#define ANA07 (0+0xCD1C)
+#define ANA08 (0+0xCD20)
+#define ANA09 (0+0xCD24)
+#define ANA0A (0+0xCD28)
+#define ANA0B (0+0xCD2C)
+#define ANA0C (0+0xCD30)
+#define ANA0D (0+0xCD34)
+#define ANA0E (0+0xCD38)
+#define ANA0F (0+0xCD3C)
+#define DMR (0+0xCD40)
+#define BACR (0+0xCD44)
+#define IER (0+0xCD48)
+#define BCSR (0+0xCD4C)
+#define BPR (0+0xCD50)
+#define BPNR2 (0+0xCD54)
+#define BFNR (0+0xCD58)
+#define BRNR2 (0+0xCD5C)
+#define BENR (0+0xCD60)
+#define REV0 (0+0xCD64)
+#define REV1 (0+0xCD68)
+#define REV2 (0+0xCD6C)
+#define REV3 (0+0xCD70)
+#define FLD0 (0+0xCD74)
+#define FLD1 (0+0xCD78)
+#define ANA1F (0+0xCD7C)
+#define PAGE1_REG00 (0+0xCD80)
+#define PAGE1_REG01 (0+0xCD84)
+#define PAGE1_REG02 (0+0xCD88)
+#define PAGE1_REG03 (0+0xCD8C)
+#define PAGE1_REG04 (0+0xCD90)
+#define PAGE1_REG05 (0+0xCD94)
+#define PAGE1_REG06 (0+0xCD98)
+#define PAGE1_REG07 (0+0xCD9C)
+#define PAGE1_REG08 (0+0xCDA0)
+#define PAGE1_REG09 (0+0xCDA4)
+#define PAGE1_REG0A (0+0xCDA8)
+#define PAGE1_REG0B (0+0xCDAC)
+#define PAGE1_REG0C (0+0xCDB0)
+#define PAGE1_REG0D (0+0xCDB4)
+#define PAGE1_REG0E (0+0xCDB8)
+#define PAGE1_REG0F (0+0xCDBC)
+#define PAGE1_REG10 (0+0xCDC0)
+#define USB2_P0_VDCTRL (0+0xCE00)
+#define BACKDOOR (0+0xCE04)
+#define EXT_CONTROL (0+0xCE08)
+#define EFUSE_CTR (0+0xCE0C)
+#define USB2_P1_VDCTRL (0+0xCE10) 
+
+
+#define USB3_ACTIONS_START        (0xcd00)
+#define USB3_ACTIONS_END          (0xcd58)
+
+#define DWC3_CDR_KIKD          (0x00)
+#define DWC3_CDR_KP1           (0x04)
+#define DWC3_TIMER_INIT        (0x08)
+#define DWC3_CDR_CONTROL       (0x0c)
+#define DWC3_RX_OFFSET_PS      (0x10)
+#define DWC3_EQ_CONTROL        (0x14)
+#define DWC3_RX_OOBS_SSC0      (0x18)
+#define DWC3_CMU_SSC1          (0x1C)
+#define DWC3_CMU_DEBUG_LDO     (0x20)
+#define DWC3_TX_AMP_DEBUG      (0x24)
+#define DWC3_Z0                (0x28)
+#define DWC3_DMR_BACR          (0x2C)
+#define DWC3_IER_BCSR          (0x30)
+#define DWC3_BPR               (0x34)
+#define DWC3_BFNR              (0x38)
+#define DWC3_BENR_REV          (0x3C)
+#define DWC3_FLD               (0x40)
+#define DWC3_CMU_PLL2_BISTDEBUG    (0x44)
+
+#define USB3_MOD_RST           (1 << 14)
+#define CMU_BIAS_EN            (1 << 20)
+
+#define BIST_QINIT(n)          ((n) << 24)
+#define EYE_HEIGHT(n)          ((n) << 20)
+#define PLL2_LOCK              (1 << 15)
+#define PLL2_RS(n)             ((n) << 12)
+#define PLL2_ICP(n)            ((n) << 10)
+#define CMU_SEL_PREDIV         (1 << 9)
+#define CMU_DIVX2              (1 << 8)
+#define PLL2_DIV(n)            ((n) << 3)
+#define PLL2_POSTDIV(n)        ((n) << 1)
+#define PLL2_PU                (1 << 0)
+
+//=============== USB3_P0_CTL define=======================
+#define     USB3_P0_CTL_LDOVREFSEL_SHIFT_IC1                                      28
+#define     USB3_P0_CTL_PLLLDOEN_IC1                                              31
+
+#define     USB3_P0_CTL_LDOVREFSEL_E                                          30
+#define     USB3_P0_CTL_LDOVREFSEL_SHIFT                                      29
+#define     USB3_P0_CTL_LDOVREFSEL_MASK                                       (0x3<<29)
+#define     USB3_P0_CTL_PLLLDOEN                                              28
+#define     USB3_P0_CTL_PLUGIN                                                25
+#define     USB3_P0_CTL_CONDET_EN                                             24
+#define     USB3_P0_CTL_WKUPBVLDEN                                            23
+#define     USB3_P0_CTL_WKUPDPEN                                              22
+#define     USB3_P0_CTL_WKUPIDUSEN                                            21
+#define     USB3_P0_CTL_WKUPVBUSEN                                            20
+#define     USB3_P0_CTL_WKUPBVLD                                              19
+#define     USB3_P0_CTL_WKUPDP                                                18
+#define     USB3_P0_CTL_WKUPID                                                17
+#define     USB3_P0_CTL_WKUPVBUS                                              16
+#define     USB3_P0_CTL_DMPUEN_P0                                             15
+#define     USB3_P0_CTL_DPPUEN_P0                                             14
+#define     USB3_P0_CTL_DMPDDIS_P0                                            13
+#define     USB3_P0_CTL_DPPDDIS_P0                                            12
+#define     USB3_P0_CTL_ID_P0                                                 11
+#define     USB3_P0_CTL_BVALID_P0                                             10
+#define     USB3_P0_CTL_SOFTID_P0                                             9
+#define     USB3_P0_CTL_SOFTIDEN_P0                                           8
+#define     USB3_P0_CTL_SOFTVBUS_P0                                           7
+#define     USB3_P0_CTL_SOFTVBUSEN_P0                                         6
+#define     USB3_P0_CTL_VBUS_P0                                               5
+#define     USB3_P0_CTL_LS_P0_E                                               4
+#define     USB3_P0_CTL_LS_P0_SHIFT                                           3
+#define     USB3_P0_CTL_LS_P0_MASK                                            (0x3<<3)
+#define     USB3_P0_CTL_VBUSTH_P0_E                                           2
+#define     USB3_P0_CTL_VBUSTH_P0_SHIFT                                       0
+#define     USB3_P0_CTL_VBUSTH_P0_MASK                                        (0x7<<0)
+
+
+#endif
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
old mode 100644
new mode 100755
index bcf83c0..cc9b692
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -129,6 +129,10 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
 
 source "drivers/usb/gadget/udc/Kconfig"
 
+# Selected by UDC drivers that support high-speed operation.
+config USB_GADGET_DUALSPEED
+	bool
+
 #
 # USB Gadget Drivers
 #
@@ -455,4 +459,13 @@ source "drivers/usb/gadget/legacy/Kconfig"
 
 endchoice
 
+config USB_ACTIONS_ADFUSERVER
+	tristate "Actions Adfuserver Gadget"
+	depends on ARCH_OWL 
+	select USB_LIBCOMPOSITE	
+	help
+	  The Actions Adfuserver Gadget is use for actions' board
+	  to upgrade firmware. It must work with actions' dwc3 
+	  driver.
+	  
 endif # USB_GADGET
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
old mode 100644
new mode 100755
index 58b4657..fa5be9a
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -20,6 +20,7 @@
 
 #include <linux/usb/composite.h>
 #include <asm/unaligned.h>
+#include <linux/kallsyms.h>
 
 #include "u_os_desc.h"
 
@@ -45,7 +46,11 @@ struct usb_os_string {
  * objects, and a "usb_composite_driver" by gluing them together along
  * with the relevant device-wide data.
  */
-
+#ifndef CONFIG_USB_GADGET_VBUS_DRAW
+#define CONFIG_USB_GADGET_VBUS_DRAW 400
+#endif
+typedef void (*FUNX)(int);
+FUNX set_delaystatus_flag;
 static struct usb_gadget_strings **get_containers_gs(
 		struct usb_gadget_string_container *uc)
 {
@@ -891,6 +896,7 @@ void usb_remove_config(struct usb_composite_dev *cdev,
 
 	remove_config(cdev, config);
 }
+EXPORT_SYMBOL(usb_remove_config);
 
 /*-------------------------------------------------------------------------*/
 
@@ -2222,6 +2228,9 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev)
 		DBG(cdev, "%s: Completing delayed status\n", __func__);
 		req->length = 0;
 		req->context = cdev;
+        	set_delaystatus_flag = (FUNX)kallsyms_lookup_name("set_no_delay_status");
+              if (set_delaystatus_flag)
+                       set_delaystatus_flag(1);   /* make sure the usb_ep_queue have done really */
 		value = composite_ep0_queue(cdev, req, GFP_ATOMIC);
 		if (value < 0) {
 			DBG(cdev, "ep_queue --> %d\n", value);
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
old mode 100644
new mode 100755
index 917d99c..16d1b84
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -713,7 +713,7 @@ static int do_read(struct fsg_common *common)
 		}
 
 		/* Perform the read */
-		file_offset_tmp = file_offset;
+		file_offset_tmp = file_offset;	
 		nread = vfs_read(curlun->filp,
 				 (char __user *)bh->buf,
 				 amount, &file_offset_tmp);
@@ -1083,7 +1083,6 @@ static int do_verify(struct fsg_common *common)
 	return 0;
 }
 
-
 /*-------------------------------------------------------------------------*/
 
 static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
@@ -1675,6 +1674,18 @@ static int send_status(struct fsg_common *common)
 		return -EIO;
 
 	common->next_buffhd_to_fill = bh->next;
+
+#ifdef SUPPORT_UDISK_UPGRADE
+  if(restart_flag == 1) {
+    set_upgrade_flags_and_restart();
+  }
+#endif
+
+#ifdef SUPPORT_SET_SERIAL_NUMBER
+	if(adfu_restart_flag == 1) {
+		gadget_andorid_shutdown_machine();
+	}
+#endif
 	return 0;
 }
 
@@ -2059,7 +2070,6 @@ static int do_scsi_command(struct fsg_common *common)
 		if (reply == 0)
 			reply = do_write(common);
 		break;
-
 	/*
 	 * Some mandatory commands that we recognize but don't implement.
 	 * They don't mean much in this setting.  It's left as an exercise
diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/gadget/function/storage_common.c
old mode 100644
new mode 100755
index 648f9e4..a4af310
--- a/drivers/usb/gadget/function/storage_common.c
+++ b/drivers/usb/gadget/function/storage_common.c
@@ -293,6 +293,24 @@ int fsg_lun_fsync_sub(struct fsg_lun *curlun)
 
 	if (curlun->ro || !filp)
 		return 0;
+#ifdef DEBUG_TIME_OF_VFS_OP
+	if(debug_vfs_op_time) {
+		struct timeval tv_start;
+		struct timeval tv_end;
+		int ret;
+
+		do_gettimeofday(&tv_start);
+
+		ret = vfs_fsync(filp, 1);
+
+		do_gettimeofday(&tv_end);
+		calculate_time_of_vfs_op(&tv_start, &tv_end);
+
+		return ret;
+	}
+	else
+		
+#endif			
 	return vfs_fsync(filp, 1);
 }
 EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub);
diff --git a/drivers/usb/gadget/legacy/Makefile b/drivers/usb/gadget/legacy/Makefile
old mode 100644
new mode 100755
index 7f485f2..2b85397
--- a/drivers/usb/gadget/legacy/Makefile
+++ b/drivers/usb/gadget/legacy/Makefile
@@ -42,3 +42,6 @@ obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
 obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
 obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
 obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
+
+adfus-y := adfuserver.o
+obj-$(CONFIG_USB_ACTIONS_ADFUSERVER)		+= adfus.o
diff --git a/drivers/usb/gadget/legacy/adfuserver.c b/drivers/usb/gadget/legacy/adfuserver.c
new file mode 100644
index 0000000..de916fc
--- /dev/null
+++ b/drivers/usb/gadget/legacy/adfuserver.c
@@ -0,0 +1,4987 @@
+/*
+ * file_storage.c -- File-backed USB Storage Gadget, for USB development
+ *
+ * Copyright (C) 2003-2007 Alan Stern
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the above-listed copyright holders may not be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The File-backed Storage Gadget acts as a USB Mass Storage device,
+ * appearing to the host as a disk drive.  In addition to providing an
+ * example of a genuinely useful gadget driver for a USB device, it also
+ * illustrates a technique of double-buffering for increased throughput.
+ * Last but not least, it gives an easy way to probe the behavior of the
+ * Mass Storage drivers in a USB host.
+ *
+ * Backing storage is provided by a regular file or a block device, specified
+ * by the "file" module parameter.  Access can be limited to read-only by
+ * setting the optional "ro" module parameter.  The gadget will indicate that
+ * it has removable media if the optional "removable" module parameter is set.
+ *
+ * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
+ * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
+ * by the optional "transport" module parameter.  It also supports the
+ * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
+ * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
+ * the optional "protocol" module parameter.  In addition, the default
+ * Vendor ID, Product ID, and release number can be overridden.
+ *
+ * There is support for multiple logical units (LUNs), each of which has
+ * its own backing file.  The number of LUNs can be set using the optional
+ * "luns" module parameter (anywhere from 1 to 8), and the corresponding
+ * files are specified using comma-separated lists for "file" and "ro".
+ * The default number of LUNs is taken from the number of "file" elements;
+ * it is 1 if "file" is not given.  If "removable" is not set then a backing
+ * file must be specified for each LUN.  If it is set, then an unspecified
+ * or empty backing filename means the LUN's medium is not loaded.
+ *
+ * Requirements are modest; only a bulk-in and a bulk-out endpoint are
+ * needed (an interrupt-out endpoint is also needed for CBI).  The memory
+ * requirement amounts to two 16K buffers, size configurable by a parameter.
+ * Support is included for both full-speed and high-speed operation.
+ *
+ * Note that the driver is slightly non-portable in that it assumes a
+ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
+ * interrupt-in endpoints.  With most device controllers this isn't an
+ * issue, but there may be some with hardware restrictions that prevent
+ * a buffer from being used by more than one endpoint.
+ *
+ * Module options:
+ *
+ *	file=filename[,filename...]
+ *				Required if "removable" is not set, names of
+ *					the files or block devices used for
+ *					backing storage
+ *	ro=b[,b...]		Default false, booleans for read-only access
+ *	removable		Default false, boolean for removable media
+ *	luns=N			Default N = number of filenames, number of
+ *					LUNs to support
+ *	stall			Default determined according to the type of
+ *					USB device controller (usually true),
+ *					boolean to permit the driver to halt
+ *					bulk endpoints
+ *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
+ *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
+ *					ATAPI, QIC, UFI, 8070, or SCSI;
+ *					also 1 - 6)
+ *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
+ *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
+ *	release=0xRRRR		Override the USB release number (bcdDevice)
+ *	buflen=N		Default N=16384, buffer size used (will be
+ *					rounded down to a multiple of
+ *					PAGE_CACHE_SIZE)
+ *
+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+ * "removable", "luns", and "stall" options are available; default values
+ * are used for everything else.
+ *
+ * The pathnames of the backing files and the ro settings are available in
+ * the attribute files "file" and "ro" in the lun<n> subdirectory of the
+ * gadget's sysfs directory.  If the "removable" option is set, writing to
+ * these files will simulate ejecting/loading the medium (writing an empty
+ * line means eject) and adjusting a write-enable tab.  Changes to the ro
+ * setting are not allowed when the medium is loaded.
+ *
+ * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
+ * The driver's SCSI command interface was based on the "Information
+ * technology - Small Computer System Interface - 2" document from
+ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
+ * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
+ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
+ * "Universal Serial Bus Mass Storage Class UFI Command Specification"
+ * document, Revision 1.0, December 14, 1998, available at
+ * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
+ */
+
+/*
+ *				Driver Design
+ *
+ * The FSG driver is fairly straightforward.  There is a main kernel
+ * thread that handles most of the work.  Interrupt routines field
+ * callbacks from the controller driver: bulk- and interrupt-request
+ * completion notifications, endpoint-0 events, and disconnect events.
+ * Completion events are passed to the main thread by wakeup calls.  Many
+ * ep0 requests are handled at interrupt time, but SetInterface,
+ * SetConfiguration, and device reset requests are forwarded to the
+ * thread in the form of "exceptions" using SIGUSR1 signals (since they
+ * should interrupt any ongoing file I/O operations).
+ *
+ * The thread's main routine implements the standard command/data/status
+ * parts of a SCSI interaction.  It and its subroutines are full of tests
+ * for pending signals/exceptions -- all this polling is necessary since
+ * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
+ * indication that the driver really wants to be running in userspace.)
+ * An important point is that so long as the thread is alive it keeps an
+ * open reference to the backing file.  This will prevent unmounting
+ * the backing file's underlying filesystem and could cause problems
+ * during system shutdown, for example.  To prevent such problems, the
+ * thread catches INT, TERM, and KILL signals and converts them into
+ * an EXIT exception.
+ *
+ * In normal operation the main thread is started during the gadget's
+ * fsg_bind() callback and stopped during fsg_unbind().  But it can also
+ * exit when it receives a signal, and there's no point leaving the
+ * gadget running when the thread is dead.  So just before the thread
+ * exits, it deregisters the gadget driver.  This makes things a little
+ * tricky: The driver is deregistered at two places, and the exiting
+ * thread can indirectly call fsg_unbind() which in turn can tell the
+ * thread to exit.  The first problem is resolved through the use of the
+ * REGISTERED atomic bitflag; the driver will only be deregistered once.
+ * The second problem is resolved by having fsg_unbind() check
+ * fsg->state; it won't try to stop the thread if the state is already
+ * FSG_STATE_TERMINATED.
+ *
+ * To provide maximum throughput, the driver uses a circular pipeline of
+ * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
+ * arbitrarily long; in practice the benefits don't justify having more
+ * than 2 stages (i.e., double buffering).  But it helps to think of the
+ * pipeline as being a long one.  Each buffer head contains a bulk-in and
+ * a bulk-out request pointer (since the buffer can be used for both
+ * output and input -- directions always are given from the host's
+ * point of view) as well as a pointer to the buffer and various state
+ * variables.
+ *
+ * Use of the pipeline follows a simple protocol.  There is a variable
+ * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
+ * At any time that buffer head may still be in use from an earlier
+ * request, so each buffer head has a state variable indicating whether
+ * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
+ * buffer head to be EMPTY, filling the buffer either by file I/O or by
+ * USB I/O (during which the buffer head is BUSY), and marking the buffer
+ * head FULL when the I/O is complete.  Then the buffer will be emptied
+ * (again possibly by USB I/O, during which it is marked BUSY) and
+ * finally marked EMPTY again (possibly by a completion routine).
+ *
+ * A module parameter tells the driver to avoid stalling the bulk
+ * endpoints wherever the transport specification allows.  This is
+ * necessary for some UDCs like the SuperH, which cannot reliably clear a
+ * halt on a bulk endpoint.  However, under certain circumstances the
+ * Bulk-only specification requires a stall.  In such cases the driver
+ * will halt the endpoint and set a flag indicating that it should clear
+ * the halt in software during the next device reset.  Hopefully this
+ * will permit everything to work correctly.  Furthermore, although the
+ * specification allows the bulk-out endpoint to halt when the host sends
+ * too much data, implementing this would cause an unavoidable race.
+ * The driver will always use the "no-stall" approach for OUT transfers.
+ *
+ * One subtle point concerns sending status-stage responses for ep0
+ * requests.  Some of these requests, such as device reset, can involve
+ * interrupting an ongoing file I/O operation, which might take an
+ * arbitrarily long time.  During that delay the host might give up on
+ * the original ep0 request and issue a new one.  When that happens the
+ * driver should not notify the host about completion of the original
+ * request, as the host will no longer be waiting for it.  So the driver
+ * assigns to each ep0 request a unique tag, and it keeps track of the
+ * tag value of the request associated with a long-running exception
+ * (device-reset, interface-change, or configuration-change).  When the
+ * exception handler is finished, the status-stage response is submitted
+ * only if the current ep0 request tag is equal to the exception request
+ * tag.  Thus only the most recently received ep0 request will get a
+ * status-stage response.
+ *
+ * Warning: This driver source file is too long.  It ought to be split up
+ * into a header file plus about 3 separate .c files, to handle the details
+ * of the Gadget, USB Mass Storage, and SCSI protocols.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/dcache.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fcntl.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kref.h>
+#include <linux/kthread.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/freezer.h>
+#include <linux/utsname.h>
+#include <linux/syscalls.h>
+#include <linux/reboot.h>
+#include <linux/of.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/kdev_t.h>
+#include <mach/hardware.h>
+
+#include <linux/string.h>
+
+//#include <mach/atc260x/atc260x.h>
+#include <linux/ctype.h>
+#include <linux/usb/composite.h>
+#include "gadget_chips.h"
+#include "adfuserver.h"
+#include <mach/bootdev.h>
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+//#include "usbstring.c"
+//#include "config.c"
+//#include "epautoconf.c"
+
+/*-------------------------------------------------------------------------*/
+
+#define DRIVER_DESC		"File-backed Storage Gadget"
+#define DRIVER_NAME		"g_file_storage"
+#define DRIVER_VERSION		"7 August 2007"
+
+static const char longname[] = DRIVER_DESC;
+static const char shortname[] = DRIVER_NAME;
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Alan Stern");
+MODULE_LICENSE("GPL");
+#if 0
+struct uparam {
+	unsigned int flash_partition;
+	unsigned int devnum_in_phypart;
+};
+#endif
+enum probatch_status {
+	PROBATCH_START = 0,
+	PROBATCH_INSTAL_FLASH,
+	PROBATCH_FINISH_INSTALL_FLASH,
+	PROBATCH_WRITE_PHY,
+	PROBATCH_FINISH_WRITE_PHY,
+	PROBATCH_FORMAT,
+	PROBATCH_FINISH_FORMAT,
+	PROBATCH_FINISH,	
+	PROBATCH_FINISH_OK,
+};
+
+/* Thanks to NetChip Technologies for donating this product ID.
+ *
+ * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures. */
+#define DRIVER_VENDOR_ID	0x10D6	/* NetChip */
+#define DRIVER_PRODUCT_ID	0x10D6
+/* Linux-USB File-backed Storage Gadget */
+
+/*
+ * This driver assumes self-powered hardware and has no way for users to
+ * trigger remote wakeup.  It uses autoconfiguration to select endpoints
+ * and endpoint addresses.
+ */
+
+#define MAJOR_OF_MMS	254
+#define MAJOR_OF_CARD	179
+#define MAJOR_OF_NAND	93
+
+#define CARD_MEDIUM	10
+#define NAND_MEDIUM	20
+#define MMS_MEDIUM	30
+
+#define WHEN_FOR_ADFU	1
+
+#ifndef CONFIG_USB_GADGET_VBUS_DRAW
+#define CONFIG_USB_GADGET_VBUS_DRAW 400
+#endif
+/* NAND directly ADFU is not ready yet, defined for debug */
+
+#define SUPPORT_DIRECT_UDISK
+unsigned char no_finish_reply;
+
+static int adfu_success_flag;
+static int need_format = 0;
+static char need_restart = 1;
+static int need_checksum = 0;
+
+static int write_mbrc = 0;
+static int write_recovery = 0;
+static int write_system = 0;
+
+#define INVALID_ADFU_CHECKSUM 0xAFAFAFAF
+static __u32 system_checksum = INVALID_ADFU_CHECKSUM;
+static __u32 misc_checksum = INVALID_ADFU_CHECKSUM;
+static __u32 recovery_checksum = INVALID_ADFU_CHECKSUM;
+
+char afinfo_name[32];
+char mbrc_name[32];
+char format_fs_name[8];
+char format_disk_name[32];
+char disk_label[][8]={
+								"bootmsg",
+								"data",
+							 	"cache",
+								"NONAME"
+							};
+char *format_disk_label;
+
+//static int first_start;
+
+static unsigned int uniSerial;
+
+/* add by hmwei */
+extern char probatch_phase[];
+int cmnd_sequence_first_flag=1;
+struct file *misc_disk_filp;
+char last_cmnd=-1;
+
+enum plugstate{
+	PLUGSTATE_A_OUT=0,
+       PLUGSTATE_B_OUT,
+	PLUGSTATE_A_IN,
+	PLUGSTATE_B_IN,
+
+};
+extern int dwc3_set_plugstate(int s);
+
+extern int set_probatch_phase(int id);
+extern int is_probatch_phase(int id);
+
+
+/*-------------------------------------------------------------------------*/
+
+#define LDBG(lun, fmt, args...) \
+	dev_dbg(&(lun)->dev , fmt , ## args)
+#define MDBG(fmt, args...) \
+	pr_debug(DRIVER_NAME ": " fmt , ## args)
+
+//	#define VERBOSE_DEBUG
+
+#ifndef DEBUG
+#undef VERBOSE_DEBUG
+#undef DUMP_MSGS
+#endif /* !DEBUG */
+
+#ifdef VERBOSE_DEBUG
+#define VLDBG  LDBG
+#else
+#define VLDBG(lun, fmt, args...) \
+	do { } while (0)
+#endif /* VERBOSE_DEBUG */
+
+#define LERROR(lun, fmt, args...) \
+	dev_err(&(lun)->dev, fmt, ## args)
+#define LWARN(lun, fmt,args...) \
+	dev_warn(&(lun)->dev, fmt, ## args)
+#define LINFO(lun, fmt, args...) \
+	dev_info(&(lun)->dev, fmt, ## args)
+
+#define MINFO(fmt, args...) \
+	pr_info(DRIVER_NAME ": " fmt , ## args)
+
+#define DBG(d, fmt, args...) \
+	dev_dbg(&(d)->gadget->dev , fmt , ## args)
+#define VDBG(d, fmt, args...) \
+	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
+#define ERROR(d, fmt, args...) \
+	dev_err(&(d)->gadget->dev , fmt , ## args)
+#define WARNING(d, fmt, args...) \
+	dev_warn(&(d)->gadget->dev , fmt , ## args)
+#define INFO(d, fmt, args...) \
+	dev_info(&(d)->gadget->dev , fmt , ## args)
+
+/*-------------------------------------------------------------------------*/
+
+/* Encapsulate the module parameter settings */
+
+#define MAX_LUNS	8
+
+/* USB protocol value = the transport method */
+#define USB_PR_CBI	0x00	/* Control/Bulk/Interrupt */
+#define USB_PR_CB	0x01	/* Control/Bulk w/o interrupt */
+#define USB_PR_BULK	0x50	/* Bulk-only */
+
+/* USB subclass value = the protocol encapsulation */
+#define USB_SC_RBC	0x01	/* Reduced Block Commands (flash) */
+#define USB_SC_8020	0x02	/* SFF-8020i, MMC-2, ATAPI (CD-ROM) */
+#define USB_SC_QIC	0x03	/* QIC-157 (tape) */
+#define USB_SC_UFI	0x04	/* UFI (floppy) */
+#define USB_SC_8070	0x05	/* SFF-8070i (removable) */
+#define USB_SC_SCSI	0x06	/* Transparent SCSI */
+
+static struct {
+	char *file[MAX_LUNS];
+	int ro[MAX_LUNS];
+	unsigned int num_filenames;
+	unsigned int num_ros;
+	unsigned int nluns;
+
+	int removable;
+	int can_stall;
+
+	char *transport_parm;
+	char *protocol_parm;
+	unsigned short vendor;
+	unsigned short product;
+	unsigned short release;
+	unsigned int buflen;
+
+	int transport_type;
+	char *transport_name;
+	int protocol_type;
+	char *protocol_name;
+
+} mod_data = {			/* Default values */
+	/* .file[0] = "/dev/actd", */
+	.transport_parm = "BBB",
+	//.protocol_parm = "SCSI",
+	.protocol_parm = "8070i",
+
+
+	.transport_type = USB_PR_BULK,      /*! transport type signed by usb-if*/
+	.transport_name = "Bulk-only",     /*! transport name*/
+	.protocol_type = USB_SC_8070,      /*! protocol type*/
+	.protocol_name = "8070i",     /*! protocol name*/
+
+	.nluns = 2,	/* tmp used by wlt 20091130 */
+	.removable = 1,
+	.can_stall = 0,
+	.vendor = DRIVER_VENDOR_ID,
+	.product = DRIVER_PRODUCT_ID,
+	.release = 0xffff,	/* Use controller chip type */
+	.buflen = 16384,
+};
+
+module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
+			 S_IRUGO);
+MODULE_PARM_DESC(file, "names of backing files or devices");
+
+
+module_param_named(uniSerial, uniSerial, uint, S_IRUGO);
+MODULE_PARM_DESC(uniSerial,
+		"1 to indicate we should report iSerialNumber as unicode mod");
+
+//MODULE_PARM_DESC(file, "names of backing files or devices");
+
+module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
+MODULE_PARM_DESC(vendor, "USB Vendor ID");
+
+module_param_named(product, mod_data.product, ushort, S_IRUGO);
+MODULE_PARM_DESC(product, "USB Product ID");
+
+module_param_named(release, mod_data.release, ushort, S_IRUGO);
+MODULE_PARM_DESC(release, "USB release number");
+
+/*-------------------------------------------------------------------------*/
+
+
+/* Bulk-only data structures */
+
+/* Command Block Wrapper */
+struct bulk_cb_wrap {
+	__le32 Signature;	/* Contains 'USBC' */
+	u32 Tag;		/* Unique per command id */
+	__le32 DataTransferLength;	/* Size of the data */
+	u8 Flags;		/* Direction in bit 7 */
+	u8 Lun;			/* LUN (normally 0) */
+	u8 Length;		/* Of the CDB, <= MAX_COMMAND_SIZE */
+	u8 CDB[16];		/* Command Data Block */
+};
+
+#define USB_BULK_CB_WRAP_LEN	31
+#define USB_BULK_CB_SIG		0x43425355	/* Spells out USBC */
+#define USB_BULK_IN_FLAG	0x80
+
+/* Command Status Wrapper */
+struct bulk_cs_wrap {
+	__le32 Signature;	/* Should = 'USBS' */
+	u32 Tag;		/* Same as original command */
+	__le32 Residue;		/* Amount not transferred */
+	u8 Status;		/* See below */
+};
+
+#define USB_BULK_CS_WRAP_LEN	13
+#define USB_BULK_CS_SIG		0x53425355	/* Spells out 'USBS' */
+#define USB_STATUS_PASS		0
+#define USB_STATUS_FAIL		1
+#define USB_STATUS_PHASE_ERROR	2
+
+/* Bulk-only class specific requests */
+#define USB_BULK_RESET_REQUEST		0xff
+#define USB_BULK_GET_MAX_LUN_REQUEST	0xfe
+
+/* CBI Interrupt data structure */
+struct interrupt_data {
+	u8 bType;
+	u8 bValue;
+};
+
+#define CBI_INTERRUPT_DATA_LEN		2
+
+/* CBI Accept Device-Specific Command request */
+#define USB_CBI_ADSC_REQUEST		0x00
+
+#define MAX_COMMAND_SIZE	16
+/* Length of a SCSI Command Data Block */
+
+/* SCSI commands that we recognize */
+#define SC_FORMAT_UNIT			0x04
+#define SC_INQUIRY			0x12
+#define SC_MODE_SELECT_6		0x15
+#define SC_MODE_SELECT_10		0x55
+#define SC_MODE_SENSE_6			0x1a
+#define SC_MODE_SENSE_10		0x5a
+#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL	0x1e
+#define SC_READ_6			0x08
+#define SC_READ_10			0x28
+#define SC_READ_12			0xa8
+#define SC_READ_CAPACITY		0x25
+#define SC_READ_FORMAT_CAPACITIES	0x23
+#define SC_RELEASE			0x17
+#define SC_REQUEST_SENSE		0x03
+#define SC_RESERVE			0x16
+#define SC_SEND_DIAGNOSTIC		0x1d
+#define SC_START_STOP_UNIT		0x1b
+#define SC_SYNCHRONIZE_CACHE		0x35
+#define SC_TEST_UNIT_READY		0x00
+#define SC_VERIFY			0x2f
+#define SC_WRITE_6			0x0a
+#define SC_WRITE_10			0x2a
+#define SC_WRITE_12			0xaa
+
+/* make sure the U-device is ACTIONS */
+#define	 SC_ACTIONS_INQUIRY		0xcc
+#define  SC_ADFU_UPGRADE		0xcd
+/* sub-code used for up-tool */
+#define	 SC_ADFU_ACCESS_MBR		0x90
+#define	 SC_ADFU_WRITE_ROOTFS		0x11
+#define	 SC_ADFU_READ_ROOTFS		0x91
+
+#define  SC_ADFU_ACCESS_INTERNAL_RAM	0x13
+
+#define  SC_ADFU_FORMAT_FLASH		0x16
+#define	 SC_ADFU_TEST_FLASHRDY		0x17
+
+/* sub-code used for u-disk upgrade */
+#define	 SC_ADFU_WRITE_FILES		0x12
+
+/* FILE TYPE PARAM */
+#define  FP_MBREC		0x01
+#define  FP_MBRINFO		0x02
+#define  FP_VMLINUX		0x03
+
+#define  SC_ADFU_TEST_READY		0x13
+
+/* TEST ACTION TYPE PARAM */
+#define  SC_ADFU_FILE_READY	0x01
+#define	 SC_ADFU_APP_READY	0x02
+
+#define	 SC_ADFU_START_APP		0x14
+#define  SC_ADFU_CREATE_FILES		0x15
+
+#define SC_ADFU_DOWNLOAD_IMG	0x60
+
+#define SC_ADFU_INFO	0xc0
+#define SC_ADFU_TFEROVER		0x30
+
+/* upgrade success-ful */
+#define  SC_ADFU_SUCCESSFUL		0xb0
+#define SS_CHECKSUM_FAIL		0x083800 
+
+/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
+#define SS_NO_SENSE				0
+#define SS_COMMUNICATION_FAILURE		0x040800
+#define SS_INVALID_COMMAND			0x052000
+#define SS_INVALID_FIELD_IN_CDB			0x052400
+#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
+#define SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
+#define SS_MEDIUM_NOT_PRESENT			0x023a00
+#define SS_MEDIUM_REMOVAL_PREVENTED		0x055302
+#define SS_NOT_READY_TO_READY_TRANSITION	0x062800
+#define SS_RESET_OCCURRED			0x062900
+#define SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
+#define SS_UNRECOVERED_READ_ERROR		0x031100
+#define SS_WRITE_ERROR				0x030c02
+#define SS_WRITE_PROTECTED			0x072700
+
+#define SK(x)		((u8) ((x) >> 16))	/* Sense Key byte, etc. */
+#define ASC(x)		((u8) ((x) >> 8))
+#define ASCQ(x)		((u8) (x))
+
+/*-------------------------------------------------------------------------*/
+
+#define transport_is_bbb()	1
+#define transport_is_cbi()	0
+
+struct lun {
+	struct file *filp;
+	loff_t file_length;
+	loff_t num_sectors;
+	u8 sector_size_mask;
+	u8 disk_type;		/* add by wlt 20091130 */
+	dev_t devnum;		/* add by wlt 20091223 */
+
+	unsigned int ro:1;
+	unsigned int prevent_medium_removal:1;
+	unsigned int registered:1;
+	unsigned int info_valid:1;
+
+	u32 sense_data;
+	u32 sense_data_info;
+	u32 unit_attention_data;
+
+	struct device dev;
+};
+
+#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
+
+static struct lun *dev_to_lun(struct device *dev)
+{
+	return container_of(dev, struct lun, dev);
+}
+
+/* Big enough to hold our biggest descriptor */
+#define EP0_BUFSIZE	256
+#define DELAYED_STATUS	(EP0_BUFSIZE + 999)	/* An impossibly large value */
+
+/* Number of buffers we will use.  2 is enough for double-buffering */
+#define NUM_BUFFERS	2
+
+
+enum fsg_buffer_state {
+	BUF_STATE_EMPTY = 0,
+	BUF_STATE_FULL,
+	BUF_STATE_BUSY
+};
+
+struct fsg_buffhd {
+	void *buf;
+	enum fsg_buffer_state state;
+	struct fsg_buffhd *next;
+
+	/* The NetChip 2280 is faster, and handles some protocol faults
+	 * better, if we don't submit any short bulk-out read requests.
+	 * So we will record the intended request length here. */
+	unsigned int bulk_out_intended_length;
+
+	struct usb_request *inreq;
+	int inreq_busy;
+	struct usb_request *outreq;
+	int outreq_busy;
+};
+
+enum fsg_state {
+	FSG_STATE_COMMAND_PHASE = -10,	/* This one isn't used anywhere */
+	FSG_STATE_DATA_PHASE,
+	FSG_STATE_STATUS_PHASE,
+
+	FSG_STATE_IDLE = 0,
+	FSG_STATE_ABORT_BULK_OUT,
+	FSG_STATE_RESET,
+	FSG_STATE_INTERFACE_CHANGE,
+	FSG_STATE_CONFIG_CHANGE,
+	FSG_STATE_DISCONNECT,
+	FSG_STATE_EXIT,
+	FSG_STATE_TERMINATED
+};
+
+enum data_direction {
+	DATA_DIR_UNKNOWN = 0,
+	DATA_DIR_FROM_HOST,
+	DATA_DIR_TO_HOST,
+	DATA_DIR_NONE
+};
+
+struct fsg_dev {
+	/* lock protects: state, all the req_busy's, and cbbuf_cmnd */
+	spinlock_t lock;
+	struct usb_gadget *gadget;
+
+	/* filesem protects: backing files in use */
+	struct rw_semaphore filesem;
+
+	/* reference counting: wait until all LUNs are released */
+	struct kref ref;
+
+	struct usb_ep *ep0;	/* Handy copy of gadget->ep0 */
+	struct usb_request *ep0req;	/* For control responses */
+	unsigned int ep0_req_tag;
+	const char *ep0req_name;
+
+	struct usb_request *intreq;	/* For interrupt responses */
+	int intreq_busy;
+	struct fsg_buffhd *intr_buffhd;
+
+	unsigned int bulk_out_maxpacket;
+	enum fsg_state state;	/* For exception handling */
+	unsigned int exception_req_tag;
+
+	u8 config, new_config;
+
+	unsigned int running:1;
+	unsigned int bulk_in_enabled:1;
+	unsigned int bulk_out_enabled:1;
+	unsigned int intr_in_enabled:1;
+	unsigned int phase_error:1;
+	unsigned int short_packet_received:1;
+	unsigned int bad_lun_okay:1;
+
+	unsigned long atomic_bitflags;
+#define REGISTERED		0
+#define IGNORE_BULK_OUT		1
+/* #define CLEAR_BULK_HALTS	1 */
+#define SUSPENDED		2
+
+	struct usb_ep *bulk_in;
+	struct usb_ep *bulk_out;
+	struct usb_ep *intr_in;
+
+	struct fsg_buffhd *next_buffhd_to_fill;
+	struct fsg_buffhd *next_buffhd_to_drain;
+	struct fsg_buffhd buffhds[NUM_BUFFERS];
+
+	int thread_wakeup_needed;
+	struct completion thread_notifier;
+	struct task_struct *thread_task;
+
+	int cmnd_size;
+	u8 cmnd[MAX_COMMAND_SIZE];
+	enum data_direction data_dir;
+	u32 data_size;
+	u32 data_size_from_cmnd;
+	u32 tag;
+	unsigned int lun;
+	u32 residue;
+	u32 usb_amount_left;
+
+	/* The CB protocol offers no way for a host to know when a command
+	 * has completed.  As a result the next command may arrive early,
+	 * and we will still have to handle it.  For that reason we need
+	 * a buffer to store new commands when using CB (or CBI, which
+	 * does not oblige a host to wait for command completion either). */
+	int cbbuf_cmnd_size;
+	u8 cbbuf_cmnd[MAX_COMMAND_SIZE];
+
+	unsigned int nluns;
+	struct lun *luns;
+	struct lun *curlun;
+};
+
+/****************************************************/
+/**** for the app to know current state of udisk ****/
+
+#define TIMEOUT (HZ * 1)
+struct status_ops {
+	unsigned long timeout;
+	wait_queue_head_t wait;
+	struct completion thread_exit;
+	unsigned char quit;
+} status_arg;
+
+#define STATE_IDLE	0
+#define STATE_READING	1
+#define STATE_WRITING	2
+
+//static unsigned int card_dirty_flag;
+//static unsigned int nand_dirty_flag;
+
+int check_partition_flag=0;//partiton update
+int update_phy_boot=0;//
+	
+/*****************************************************/
+//static int do_ADFU_acmbr(struct fsg_dev *);
+static int do_ADFU_wtrootfs(struct fsg_dev *);
+static void handle_exception(struct fsg_dev *fsg);
+//static int open_backing_file(struct lun *curlun, const char *filename);
+
+extern void machine_restart(char *cmd);
+
+typedef void (*fsg_routine_t)(struct fsg_dev *);
+
+static int exception_in_progress(struct fsg_dev *fsg)
+{
+	return fsg->state > FSG_STATE_IDLE;
+}
+
+/* Make bulk-out requests be divisible by the maxpacket size */
+static void set_bulk_out_req_length(struct fsg_dev *fsg,
+				    struct fsg_buffhd *bh, unsigned int length)
+{
+	unsigned int	rem; 
+
+	bh->bulk_out_intended_length = length;
+	rem = length % fsg->bulk_out_maxpacket;
+	if (rem > 0)
+		length += fsg->bulk_out_maxpacket - rem; 
+	bh->outreq->length = length;
+}
+
+static struct fsg_dev *the_fsg;
+static struct usb_gadget_driver fsg_driver;
+
+static void close_backing_file(struct lun *curlun);
+static void close_all_backing_files(struct fsg_dev *fsg);
+
+/*-------------------------------------------------------------------------*/
+static int act_gadget_is_dualspeed(struct usb_gadget *g)
+{
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+#ifdef DUMP_MSGS
+
+static void dump_msg(struct fsg_dev *fsg, const char *label,
+		     const u8 *buf, unsigned int length)
+{
+	if (length < 512) {
+		DBG(fsg, "%s, length %u:\n", label, length);
+		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
+			       16, 1, buf, length, 0);
+	}
+}
+
+static void dump_cdb(struct fsg_dev *fsg)
+{
+}
+
+#else
+
+static void dump_msg(struct fsg_dev *fsg, const char *label,
+		     const u8 *buf, unsigned int length)
+{
+}
+
+#ifdef VERBOSE_DEBUG
+
+static void dump_cdb(struct fsg_dev *fsg)
+{
+	print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,
+		       16, 1, fsg->cmnd, fsg->cmnd_size, 0);
+}
+
+#else
+
+static void dump_cdb(struct fsg_dev *fsg)
+{
+}
+
+#endif /* VERBOSE_DEBUG */
+#endif /* DUMP_MSGS */
+
+#define EP_STALL (1<<6)
+static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
+{
+	const char *name;
+
+	if (ep == fsg->bulk_in)
+		name = "bulk-in";
+	else if (ep == fsg->bulk_out)
+		name = "bulk-out";
+	else
+		name = ep->name;
+	DBG(fsg, "%s set halt\n", name);
+	return usb_ep_set_halt(ep);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Routines for unaligned data access */
+
+static u32 get_le32(u8 *buf)
+{
+	return ((u32) buf[3] << 24) | ((u32) buf[2] << 16) |
+	    ((u32) buf[1] << 8) | ((u32) buf[0]);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * DESCRIPTORS ... most are static, but strings and (full) configuration
+ * descriptors are built on demand.  Also the (static) config and interface
+ * descriptors are adjusted during fsg_bind().
+ */
+#define STRING_MANUFACTURER	1
+#define STRING_PRODUCT		2
+#define STRING_SERIAL		3
+#define STRING_CONFIG		4
+#define STRING_INTERFACE	5
+
+/* There is only one configuration. */
+#define	CONFIG_VALUE		1
+
+static struct usb_device_descriptor device_desc = {
+	.bLength = sizeof device_desc,
+	.bDescriptorType = USB_DT_DEVICE,
+
+	.bcdUSB = __constant_cpu_to_le16(0x0200),
+	.bDeviceClass = USB_CLASS_PER_INTERFACE,
+
+	/* The next three values can be overridden by module parameters */
+	.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
+	.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
+	.bcdDevice = __constant_cpu_to_le16(0x0100),
+
+	.iManufacturer = 0,
+	.iProduct = 0,
+	.iSerialNumber = 0,
+	.bNumConfigurations = 1,
+};
+
+static struct usb_config_descriptor config_desc = {
+	.bLength = sizeof config_desc,
+	.bDescriptorType = USB_DT_CONFIG,
+
+	/* wTotalLength computed by usb_gadget_config_buf() */
+	.bNumInterfaces = 1,
+	.bConfigurationValue = CONFIG_VALUE,
+	.iConfiguration = STRING_CONFIG,
+	/*.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, */
+	.bmAttributes = USB_CONFIG_ATT_ONE,
+	/*.bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, */
+	.bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW,
+};
+
+static struct usb_otg_descriptor otg_desc = {
+	.bLength = sizeof(otg_desc),
+	.bDescriptorType = USB_DT_OTG,
+
+	.bmAttributes = USB_OTG_SRP,
+};
+
+/* There is only one interface. */
+
+static struct usb_interface_descriptor intf_desc = {
+	.bLength = sizeof intf_desc,
+	.bDescriptorType = USB_DT_INTERFACE,
+
+	.bNumEndpoints = 2,	/* Adjusted during fsg_bind() */
+	.bInterfaceClass = 0xff,
+	.bInterfaceSubClass = 0xff,	/* Adjusted during fsg_bind() */
+	.bInterfaceProtocol = 0xff,	/* Adjusted during fsg_bind() */
+	.iInterface = STRING_INTERFACE,
+};
+
+/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
+ * and interrupt-in. */
+
+static struct usb_endpoint_descriptor fs_bulk_in_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bEndpointAddress = USB_DIR_IN,
+	.bmAttributes = USB_ENDPOINT_XFER_BULK,
+	/* wMaxPacketSize set by autoconfiguration */
+};
+
+static struct usb_endpoint_descriptor fs_bulk_out_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bEndpointAddress = USB_DIR_OUT,
+	.bmAttributes = USB_ENDPOINT_XFER_BULK,
+	/* wMaxPacketSize set by autoconfiguration */
+};
+
+static struct usb_endpoint_descriptor fs_intr_in_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	.bEndpointAddress = USB_DIR_IN,
+	.bmAttributes = USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize = __constant_cpu_to_le16(2),
+	.bInterval = 32,	/* frames -> 32 ms */
+};
+
+static const struct usb_descriptor_header *fs_function[] = {
+	(struct usb_descriptor_header *)&otg_desc,
+	(struct usb_descriptor_header *)&intf_desc,
+	(struct usb_descriptor_header *)&fs_bulk_in_desc,
+	(struct usb_descriptor_header *)&fs_bulk_out_desc,
+	(struct usb_descriptor_header *)&fs_intr_in_desc,
+	NULL,
+};
+
+#define FS_FUNCTION_PRE_EP_ENTRIES	2
+
+/*
+ * USB 2.0 devices need to expose both high speed and full speed
+ * descriptors, unless they only run at full speed.
+ *
+ * That means alternate endpoint descriptors (bigger packets)
+ * and a "device qualifier" ... plus more construction options
+ * for the config descriptor.
+ */
+static struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength = sizeof dev_qualifier,
+	.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
+
+	.bcdUSB = __constant_cpu_to_le16(0x0200),
+	.bDeviceClass = USB_CLASS_PER_INTERFACE,
+
+	.bNumConfigurations = 1,
+};
+
+static struct usb_endpoint_descriptor hs_bulk_in_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
+	.bmAttributes = USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_bulk_out_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
+	.bmAttributes = USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize = __constant_cpu_to_le16(512),
+	.bInterval = 1,		/* NAK every 1 uframe */
+};
+
+static struct usb_endpoint_descriptor hs_intr_in_desc = {
+	.bLength = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType = USB_DT_ENDPOINT,
+
+	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
+	.bmAttributes = USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize = __constant_cpu_to_le16(2),
+	.bInterval = 9,		/* 2**(9-1) = 256 uframes -> 32 ms */
+};
+
+static const struct usb_descriptor_header *hs_function[] = {
+	(struct usb_descriptor_header *)&otg_desc,
+	(struct usb_descriptor_header *)&intf_desc,
+	(struct usb_descriptor_header *)&hs_bulk_in_desc,
+	(struct usb_descriptor_header *)&hs_bulk_out_desc,
+	(struct usb_descriptor_header *)&hs_intr_in_desc,
+	NULL,
+};
+
+#define HS_FUNCTION_PRE_EP_ENTRIES	2
+
+/* Maxpacket and other transfer characteristics vary by speed. */
+static struct usb_endpoint_descriptor
+*ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor
+			*fs, struct usb_endpoint_descriptor
+			*hs)
+{
+	/* printk(KERN_INFO "act_gadget_is_dualspeed:0x%x.\n",
+		act_gadget_is_dualspeed(g));
+	   printk(KERN_INFO "%d",
+		g->speed == USB_SPEED_HIGH); */
+	if (act_gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+	{
+		printk("reutrn hs\n");
+		return hs;
+	}
+		printk("reutrn fs, 0x%x, 0x%x,0x%x\n",act_gadget_is_dualspeed(g),g->speed,USB_SPEED_HIGH );
+	return fs;
+}
+
+/* The CBI specification limits the serial string to 12 uppercase hexadecimal
+ * characters. */
+static char manufacturer[64];
+static char serial[13];
+module_param_string(iSerialNumber, serial, 13, S_IRUGO);
+
+/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
+static struct usb_string strings[] = {
+	{STRING_MANUFACTURER, manufacturer},
+	{STRING_PRODUCT, longname},
+	{STRING_SERIAL, serial},
+	{STRING_CONFIG, "Bus-powered"},
+	{STRING_INTERFACE, "Mass Storage"},
+	{}
+};
+
+static struct usb_gadget_strings stringtab = {
+	.language = 0x0409,	/* en-us */
+	.strings = strings,
+};
+
+int wait_adfus_proc(int probatch_phase)
+{
+	int ret;
+	while(1)
+	{
+		ret = is_probatch_phase(probatch_phase);
+		if(ret == 0)
+		{
+			break;
+		}
+		VLDBG("schedule_timeout 1000,ret:%d,probatch_phase:%s\n",ret, probatch_phase);
+		schedule_timeout_interruptible(msecs_to_jiffies(1000));	
+	}
+	
+	return ret;
+}
+
+unsigned int nand_part[MAX_PARTITION];
+mbr_info_t *mbr_info_buf;
+
+//typedef unsigned int (*func_t)(unsigned int *, mbr_info_t *);
+//extern func_t AdfuUpdateMbrFromPhyToUsr;
+//EXPORT_SYMBOL(AdfuUpdateMbrFromPhyToUsr);
+
+//typedef void (*func_t1)(void);
+//extern func_t1 adfu_flush_nand_cache;
+//EXPORT_SYMBOL(adfu_flush_nand_cache);
+
+//int adfus_register_func_cb(unsigned int func)
+//typedef int (*func_t4)(unsigned long, unsigned long , void *, struct uparam *);
+
+//extern func_t4 adfus_nand_read;
+//extern func_t4 adfus_nand_write;
+//EXPORT_SYMBOL(adfus_nand_read);
+//EXPORT_SYMBOL(adfus_nand_write);
+
+/*
+ * Config descriptors must agree with the code that sets configurations
+ * and with code managing interfaces and their altsettings.  They must
+ * also handle different speeds and other-speed requests.
+ */
+static int populate_config_buf(struct usb_gadget *gadget,
+			       u8 *buf, u8 type, unsigned index)
+{
+	enum usb_device_speed speed = gadget->speed;
+	int len;
+	const struct usb_descriptor_header **function;
+
+	if (index > 0)
+		return -EINVAL;
+
+	if (act_gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
+		speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
+	if (act_gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH)
+		function = hs_function;
+	else
+		function = fs_function;
+
+	/* for now, don't advertise srp-only devices */
+	if (!gadget_is_otg(gadget))
+		function++;
+
+	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
+	((struct usb_config_descriptor *)buf)->bDescriptorType = type;
+	return len;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* These routines may be called in process context or in_irq */
+
+/* Caller must hold fsg->lock */
+static void wakeup_thread(struct fsg_dev *fsg)
+{
+	/* Tell the main thread that something has happened */
+	fsg->thread_wakeup_needed = 1;
+	if (fsg->thread_task)
+		wake_up_process(fsg->thread_task);
+}
+
+static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
+{
+	unsigned long flags;
+
+	/* Do nothing if a higher-priority exception is already in progress.
+	 * If a lower-or-equal priority exception is in progress, preempt it
+	 * and notify the main thread by sending it a signal. */
+	spin_lock_irqsave(&fsg->lock, flags);
+	if (fsg->state <= new_state) {
+		fsg->exception_req_tag = fsg->ep0_req_tag;
+		fsg->state = new_state;
+		if (fsg->thread_task) {
+			send_sig_info(SIGUSR1, SEND_SIG_FORCED,
+				      fsg->thread_task);
+		}
+	}
+	spin_unlock_irqrestore(&fsg->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* The disconnect callback and ep0 routines.  These always run in_irq,
+ * except that ep0_queue() is called in the main thread to acknowledge
+ * completion of various requests: set config, set interface, and
+ * Bulk-only device reset. */
+
+static void fsg_disconnect(struct usb_gadget *gadget)
+{
+	struct fsg_dev *fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "disconnect or port reset\n");
+	raise_exception(fsg, FSG_STATE_DISCONNECT);
+}
+
+static int ep0_queue(struct fsg_dev *fsg)
+{
+	int rc;
+
+	rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
+	if (rc != 0 && rc != -ESHUTDOWN) {
+
+		/* We can't do much more than wait for a reset */
+		WARNING(fsg, "error in submission: %s --> %d\n",
+			fsg->ep0->name, rc);
+	}
+	return rc;
+}
+
+static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_dev *fsg = ep->driver_data;
+
+	if (req->actual > 0)
+		dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
+	if (req->status || req->actual != req->length)
+		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+		    req->status, req->actual, req->length);
+	if (req->status == -ECONNRESET)	/* Request was cancelled */
+		usb_ep_fifo_flush(ep);
+
+	if (req->status == 0 && req->context)
+		((fsg_routine_t) (req->context)) (fsg);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Bulk and interrupt endpoint completion handlers.
+ * These always run in_irq. */
+
+static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_dev *fsg = ep->driver_data;
+	//struct lun *curlun = fsg->curlun;
+	//dev_t media_dev_t = curlun->devnum;
+	//struct block_device *bdev_back;
+	struct fsg_buffhd *bh = req->context;
+
+	//bdev_back = bdget(media_dev_t);
+
+	if (req->status || req->actual != req->length)
+		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+		    req->status, req->actual, req->length);
+	if (req->status == -ECONNRESET)	/* Request was cancelled */
+		usb_ep_fifo_flush(ep);
+	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
+	spin_lock(&fsg->lock);
+	bh->inreq_busy = 0;
+	bh->state = BUF_STATE_EMPTY;
+	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
+
+	/* when adfu upgrade successful, disconnect and sync */
+	if (unlikely(adfu_success_flag == 1)) {
+		//adfu_flush_nand_cache();
+		printk(KERN_INFO "UPGRADE SUCCESSFULLY\n");
+		raise_exception(fsg, FSG_STATE_DISCONNECT);
+	}
+
+}
+
+static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_dev *fsg = ep->driver_data;
+	struct fsg_buffhd *bh = req->context;
+
+	dump_msg(fsg, "bulk-out", req->buf, req->actual);
+	if (req->status || req->actual != bh->bulk_out_intended_length)
+		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+		    req->status, req->actual, bh->bulk_out_intended_length);
+	if (req->status == -ECONNRESET)	/* Request was cancelled */
+		usb_ep_fifo_flush(ep);
+
+	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
+	spin_lock(&fsg->lock);
+	bh->outreq_busy = 0;
+	bh->state = BUF_STATE_FULL;
+	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
+}
+
+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
+{
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Ep0 class-specific handlers.  These always run in_irq. */
+
+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+{
+}
+
+static int class_setup_req(struct fsg_dev *fsg,
+			   const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_request *req = fsg->ep0req;
+	int value = -EOPNOTSUPP;
+	u16 w_index = le16_to_cpu(ctrl->wIndex);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 w_length = le16_to_cpu(ctrl->wLength);
+
+	if (!fsg->config)
+		return value;
+
+	/* Handle Bulk-only class-specific requests */
+	if (transport_is_bbb()) {
+		switch (ctrl->bRequest) {
+
+		case USB_BULK_RESET_REQUEST:
+		/* printk(KERN_INFO "****USB_BULK_RESET_REQUEST****\n"); */
+			if (ctrl->bRequestType != (USB_DIR_OUT |
+						   USB_TYPE_CLASS |
+						   USB_RECIP_INTERFACE))
+				break;
+			if ((w_index != 0) || (w_value != 0)
+				|| (w_length !=0)) {
+				value = -EDOM;
+				break;
+			}
+
+			/* Raise an exception to stop the current operation
+			 * and reinitialize our state. */
+			DBG(fsg, "bulk reset request\n");
+			raise_exception(fsg, FSG_STATE_RESET);
+			value = DELAYED_STATUS;
+			break;
+
+		case USB_BULK_GET_MAX_LUN_REQUEST:
+		/* printk(KERN_INFO
+			"****USB_BULK_GET_MAX_LUN_REQUEST****\n"); */
+			if (ctrl->bRequestType != (USB_DIR_IN |
+						   USB_TYPE_CLASS |
+						   USB_RECIP_INTERFACE))
+				break;
+			if ((w_index != 0) || (w_value != 0)
+				|| (w_length !=1)) {
+				value = -EDOM;
+				break;
+			}
+			VDBG(fsg, "get max LUN\n");
+			*(u8 *) req->buf = fsg->nluns - 1;
+			value = 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* Handle CBI class-specific requests */
+	else {
+		switch (ctrl->bRequest) {
+
+		case USB_CBI_ADSC_REQUEST:
+			if (ctrl->bRequestType != (USB_DIR_OUT |
+						   USB_TYPE_CLASS |
+						   USB_RECIP_INTERFACE))
+				break;
+			if (w_index != 0 || w_value != 0) {
+				value = -EDOM;
+				break;
+			}
+			if (w_length > MAX_COMMAND_SIZE) {
+				value = -EOVERFLOW;
+				break;
+			}
+			value = w_length;
+			fsg->ep0req->context = received_cbi_adsc;
+			break;
+		}
+	}
+
+	if (value == -EOPNOTSUPP)
+		VDBG(fsg,
+		     "unknown class-specific control req "
+		     "%02x.%02x v%04x i%04x l%u\n",
+		     ctrl->bRequestType, ctrl->bRequest,
+		     le16_to_cpu(ctrl->wValue), w_index, w_length);
+	return value;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Ep0 standard request handlers.  These always run in_irq. */
+
+static int standard_setup_req(struct fsg_dev *fsg,
+			      const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_request *req = fsg->ep0req;
+	int value = -EOPNOTSUPP;
+	u16 w_index = le16_to_cpu(ctrl->wIndex);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+
+	/* Usually this just stores reply data in the pre-allocated ep0 buffer,
+	 * but config change events will also reconfigure hardware. */
+	switch (ctrl->bRequest) {
+
+	case USB_REQ_GET_DESCRIPTOR:
+		/* printk(KERN_INFO "****USB_REQ_GET_DESCRIPTOR_\n");*/
+		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
+					   USB_RECIP_DEVICE)) {
+			printk("DING!!\n");
+			break;
+		}
+		switch (w_value >> 8) {
+
+		case USB_DT_DEVICE:
+			/* printk(KERN_INFO "**** GET_DEVICE_DESC ****\n"); */
+			VDBG(fsg, "get device descriptor\n");
+			device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
+			value = sizeof device_desc;
+			memcpy(req->buf, &device_desc, value);
+			break;
+		case USB_DT_DEVICE_QUALIFIER:
+			/* printk(KERN_INFO "QUALIFIER****\n"); */
+			VDBG(fsg, "get device qualifier\n");
+			if (!act_gadget_is_dualspeed(fsg->gadget))
+				break;
+			dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
+			value = sizeof dev_qualifier;
+			memcpy(req->buf, &dev_qualifier, value);
+			break;
+
+		case USB_DT_OTHER_SPEED_CONFIG:
+			/* printk(KERN_INFO "OTHER_SPEED_CONFIG****\n"); */
+			VDBG(fsg, "get other-speed config descriptor\n");
+			if (!act_gadget_is_dualspeed(fsg->gadget))
+				break;
+			goto get_config;
+		case USB_DT_CONFIG:
+			/* printk(KERN_INFO "DT_CONFIG****\n"); */
+			VDBG(fsg, "get configuration descriptor\n");
+get_config:
+			value = populate_config_buf(fsg->gadget,
+						    req->buf,
+						    w_value >> 8,
+						    w_value & 0xff);
+			break;
+
+		case USB_DT_STRING:
+			/* printk(KERN_INFO "DT_STRING****\n"); */
+			VDBG(fsg, "get string descriptor\n");
+
+			/* wIndex == language code */
+			value = usb_gadget_get_string(&stringtab,
+						      w_value & 0xff, req->buf);
+			break;
+		default:
+			break;
+		}
+		break;
+
+		/* One config, two speeds */
+	case USB_REQ_SET_CONFIGURATION:
+		/* printk(KERN_INFO "****USB_REQ_SET_CONFIGURATION****\n"); */
+		if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
+					   USB_RECIP_DEVICE))
+			break;
+		VDBG(fsg, "set configuration\n");
+		if (w_value == CONFIG_VALUE || w_value == 0) {
+			/* printk(KERN_INFO
+			   "The w_value is 0x%x.\n",w_value); */
+			fsg->new_config = w_value;
+
+			/* Raise an exception to wipe out previous transaction
+			 * state (queued bufs, etc) and set the new config. */
+			raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
+			/* wakeup_thread(fsg);
+			wakeup_thread(fsg);
+			handle_exception(fsg); */
+			/* wakeup_thread(fsg); */
+			value = DELAYED_STATUS;
+		}
+		break;
+	case USB_REQ_GET_CONFIGURATION:
+		/* printk(KERN_INFO "****USB_REQ_GET_CONFIGUATION****\n"); */
+		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
+					   USB_RECIP_DEVICE))
+			break;
+		VDBG(fsg, "get configuration\n");
+		*(u8 *) req->buf = fsg->config;
+		value = 1;
+		break;
+
+	case USB_REQ_SET_INTERFACE:
+		/* printk(KERN_INFO "****USB_REQ_SET_INTERFACE****\n"); */
+		if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
+					   USB_RECIP_INTERFACE))
+			break;
+		if (fsg->config && w_index == 0) {
+
+			/* Raise an exception to wipe out previous transaction
+			 * state (queued bufs, etc) and install the new
+			 * interface altsetting. */
+			raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
+			value = DELAYED_STATUS;
+		}
+		break;
+	case USB_REQ_GET_INTERFACE:
+		/* printk(KERN_INFO "****USB_REQ_GET_INTERFACE****\n"); */
+		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
+					   USB_RECIP_INTERFACE))
+			break;
+		if (!fsg->config)
+			break;
+		if (w_index != 0) {
+			value = -EDOM;
+			break;
+		}
+		VDBG(fsg, "get interface\n");
+		*(u8 *) req->buf = 0;
+		value = 1;
+		break;
+
+	default:
+		printk("unknown control req %02x.%02x v%04x i%04x l%u\n",
+		     ctrl->bRequestType, ctrl->bRequest,
+		     w_value, w_index, le16_to_cpu(ctrl->wLength));
+		/* printk(KERN_INFO "*****UNKNOWN_CONTROL_REQ*****.\n"); */
+	}
+	return value;
+}
+
+static int fsg_setup(struct usb_gadget *gadget,
+		     const struct usb_ctrlrequest *ctrl)
+{
+	struct fsg_dev *fsg = get_gadget_data(gadget);
+	int rc;
+	int w_length = le16_to_cpu(ctrl->wLength);
+
+	++fsg->ep0_req_tag;	/* Record arrival of a new request */
+	fsg->ep0req->context = NULL;
+	fsg->ep0req->length = 0;
+	dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
+
+	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
+		rc = class_setup_req(fsg, ctrl);
+	else
+		rc = standard_setup_req(fsg, ctrl);
+
+	/* Respond with data/status or defer until later? */
+	if (rc >= 0 && rc != DELAYED_STATUS) {
+		rc = min(rc, w_length);
+		fsg->ep0req->length = rc;
+		fsg->ep0req->zero = rc < w_length;
+		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
+				    "ep0-in" : "ep0-out");
+		rc = ep0_queue(fsg);
+	}
+
+	/* Device either stalls (rc < 0) or reports success */
+	return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* All the following routines run in process context */
+
+/* Use this for bulk or interrupt transfers, not ep0 */
+static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
+			   struct usb_request *req, int *pbusy,
+			   enum fsg_buffer_state *state)
+{
+	int rc;
+	unsigned long flag;
+
+	if (ep == fsg->bulk_in)
+		dump_msg(fsg, "bulk-in", req->buf, req->length);
+	else if (ep == fsg->intr_in)
+		dump_msg(fsg, "intr-in", req->buf, req->length);
+	spin_lock_irqsave(&fsg->lock, flag);
+	*pbusy = 1;
+	*state = BUF_STATE_BUSY;
+	spin_unlock_irqrestore(&fsg->lock, flag);
+	rc = usb_ep_queue(ep, req, GFP_KERNEL);
+	if (rc != 0) {
+		printk(KERN_INFO "usb_ep_queue error !!!\n");
+		*pbusy = 0;
+		*state = BUF_STATE_EMPTY;
+
+		/* We can't do much more than wait for a reset */
+
+		/* Note: currently the net2280 driver fails zero-length
+		 * submissions if DMA is enabled. */
+		if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
+					  req->length == 0))
+			WARNING(fsg, "error in submission: %s --> %d\n",
+				ep->name, rc);
+	}
+
+	return;
+}
+
+static int sleep_thread(struct fsg_dev *fsg)
+{
+	int rc = 0;
+
+	/* Wait until a signal arrives or we are woken up */
+	for (;;) {
+		try_to_freeze();
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (signal_pending(current)) {
+			rc = -EINTR;
+			break;
+		}
+		if (fsg->thread_wakeup_needed)
+			break;
+		schedule();
+	}
+	__set_current_state(TASK_RUNNING);
+	fsg->thread_wakeup_needed = 0;
+	return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+#if 0
+static int do_ADFU_rdrootfs(struct fsg_dev *fsg)
+{
+	struct lun *curlun = fsg->curlun;
+	dev_t media_dev_t;
+	struct block_device *bdev_back;
+	struct gendisk *disk;
+
+	u32 lba;
+	struct fsg_buffhd *bh;
+	int rc;
+	u32 amount_left;
+	loff_t file_offset, file_offset_tmp;
+	struct uparam rd_param;
+	unsigned int amount;
+	ssize_t nread;
+
+	/* Get the starting Logical Block Address and check that it's
+	 * not too big */
+
+	lba = get_le32(&fsg->cmnd[5]);
+#if 0
+	if (lba >= curlun->num_sectors) {
+		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+		return -EINVAL;
+	}
+#endif
+	rd_param.flash_partition = fsg->cmnd[3];
+	rd_param.devnum_in_phypart = fsg->cmnd[4];
+
+	/* Carry out the file reads */
+	file_offset = lba;
+	amount_left = fsg->data_size_from_cmnd;
+
+	if (unlikely(amount_left == 0))
+	{
+		//printk("return:%d\n",__LINE__);
+		return -EIO;	/* No default reply */
+	}
+
+	for (;;) {
+
+		/* Figure out how much we need to read:
+		 * Try to read the remaining amount.
+		 * But don't read more than the buffer size.
+		 * And don't try to read past the end of the file.
+		 * Finally, if we're not at a page boundary, don't read past
+		 *      the next page.
+		 * If this means reading 0 then we were asked to read past
+		 *      the end of file. */
+		amount = min((unsigned int)amount_left, mod_data.buflen);
+		/*
+		amount = min((loff_t) amount,
+			     curlun->file_length - file_offset);
+		partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
+		if (partial_page > 0)
+			amount = min(amount, (unsigned int)PAGE_CACHE_SIZE -
+				     partial_page);
+		*/
+		/* Wait for the next buffer to become available */
+		bh = fsg->next_buffhd_to_fill;
+		while (bh->state != BUF_STATE_EMPTY) {
+			rc = sleep_thread(fsg);
+			if (rc)
+			{
+				//printk("return:%d\n",__LINE__);
+				return rc;
+			}
+		}
+
+		/* If we were asked to read past the end of file,
+		 * end with an empty buffer. */
+		/*
+		if (amount == 0) {
+			curlun->sense_data =
+			    SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+			curlun->sense_data_info = file_offset;
+			curlun->info_valid = 1;
+			bh->inreq->length = 0;
+			bh->state = BUF_STATE_FULL;
+			break;
+		}
+		*/
+		/* Perform the read */
+		amount = amount << 9; /* unit by sector */
+		file_offset_tmp = file_offset;
+		media_dev_t = curlun->devnum;
+		bdev_back = bdget(media_dev_t);
+		disk = bdev_back->bd_disk;
+		//nread = disk->fops->adfu_read(file_offset, amount,
+		//		bh->buf, &rd_param);
+		nread = vfs_read(curlun->filp,
+				 (char __user *)bh->buf,
+				 amount, &file_offset_tmp);
+
+#if 0
+		nread = vfs_read(curlun->filp,
+				 (char __user *)bh->buf,
+				 amount, &file_offset_tmp);
+#endif
+		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
+		      (unsigned long long)file_offset, (int)nread);
+		if (signal_pending(current)) {
+			bdput(bdev_back);
+			//printk("return:%d\n",__LINE__);
+			return -EINTR;
+		}
+		if (nread < 0) {
+			LDBG(curlun, "error in file read: %d\n", (int)nread);
+			nread = 0;
+		} else if (nread < amount) {
+			LDBG(curlun, "partial file read: %d/%u\n",
+			     (int)nread, amount);
+		}
+		file_offset += nread;
+		amount_left -= (((unsigned int)nread) << 9);
+		fsg->residue -= (((unsigned int)nread) << 9);
+		bh->inreq->length = (((unsigned int)nread) << 9);
+		bh->state = BUF_STATE_FULL;
+
+		/* If an error occurred, report it and its position */
+		if (nread < amount) {
+			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
+			curlun->sense_data_info = file_offset;
+			curlun->info_valid = 1;
+			break;
+		}
+
+		if (amount_left == 0)
+			break;	/* No more left to read */
+
+		/* Send this buffer and go read some more */
+		bh->inreq->zero = 0;
+		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+			       &bh->inreq_busy, &bh->state);
+		fsg->next_buffhd_to_fill = bh->next;
+	}
+	no_finish_reply = 0;	/* the last buf has not been transfered,
+				   move it into finish_reply() */
+	bdput(bdev_back);
+	//printk("return:%d\n",__LINE__);
+	return -EIO;		/* No default reply */
+}
+#endif
+static int get_udisk_size(struct lun *curlun, const char *filename)
+{
+	int ro;
+	struct file *filp = NULL;
+	int rc = -EINVAL;
+	struct inode *inode = NULL;
+	loff_t size;
+	loff_t num_sectors;
+
+	/* R/W if we can, R/O if we must */
+	ro = curlun->ro;
+	if (!ro) {
+		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
+		if (-EROFS == PTR_ERR(filp))
+			ro = 1;
+	}
+	if (ro)
+		filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
+	if (IS_ERR(filp)) {
+		LINFO(curlun, "unable to open backing file: %s\n", filename);
+		return PTR_ERR(filp);
+	}
+
+	if (!(filp->f_mode & FMODE_WRITE))
+		ro = 1;
+
+	if (filp->f_path.dentry)
+		inode = filp->f_path.dentry->d_inode;
+	if (inode && S_ISBLK(inode->i_mode)) {
+		if (bdev_read_only(inode->i_bdev))
+			ro = 1;
+	} else if (!inode || !S_ISREG(inode->i_mode)) {
+		LINFO(curlun, "invalid file type: %s\n", filename);
+		goto out;
+	}
+
+	/* If we can't read the file, it's no good.
+	 * If we can't write the file, use it read-only. */
+	if (!filp->f_op || !(filp->f_op->read || filp->f_op->read_iter)) {
+		LINFO(curlun, "file not readable: %s\n", filename);
+		goto out;
+	}
+	if (!(filp->f_op->write || filp->f_op->write_iter))
+		ro = 1;
+
+	size = i_size_read(inode->i_mapping->host);
+	if (size < 0) {
+		LINFO(curlun, "unable to find file size: %s\n", filename);
+		rc = (int)size;
+		goto out;
+	}
+	num_sectors = size >> 9;	/* File size in 512-byte sectors */
+	if (num_sectors == 0) {
+		LINFO(curlun, "file too small: %s\n", filename);
+		rc = -ETOOSMALL;
+		goto out;
+	}
+
+	get_file(filp);
+
+	curlun->devnum = filp->f_path.dentry->d_inode->i_rdev;
+
+	curlun->ro = ro;
+	curlun->filp = filp;
+	curlun->file_length = size;
+	curlun->num_sectors = num_sectors;
+	LDBG(curlun, "open backing file: %s\n", filename);
+	rc = 0;
+
+out:
+	filp_close(filp, current->files);
+	return rc;
+}
+static int do_ADFU_check_partition(struct fsg_dev *fsg)
+{
+	struct fsg_buffhd *bh;
+	int rc, ret;
+	loff_t file_offset_byte;
+	u32 amount_left;
+	unsigned int amount;
+	ssize_t nread;
+	unsigned int tmp;
+	struct file *f_filp;
+    struct lun *curlun = fsg->curlun;
+	int rc2 = -EINVAL;
+	char buf[4];
+	int size = 1;
+
+	if(cmnd_sequence_first_flag)	//wait insmod flash
+	{
+		set_probatch_phase(PROBATCH_INSTAL_FLASH);
+		wait_adfus_proc(PROBATCH_FINISH_INSTALL_FLASH);//sync with upgrade_app
+		cmnd_sequence_first_flag = 0;
+		check_partition_flag = 0;
+		// add by lty
+		f_filp = filp_open("/usr/flash_check", O_RDONLY, 0644);
+		if (  f_filp != NULL ) { // 
+			file_offset_byte = 0;
+			buf[0] = 0;
+			ret = vfs_read(f_filp, buf, 2, &file_offset_byte);
+			filp_close(f_filp, current->files);
+			if ( buf[0] != '0' ) {
+				check_partition_flag = buf[0]-'0';
+				check_partition_flag = -check_partition_flag;
+			}
+			printk("read install flash return ret=%d, val=%d, flag=%d\n",ret, buf[0], check_partition_flag);
+			
+		} else {
+			printk("open /usr/flash_check fail\n");
+		}
+	    rc2=get_udisk_size(curlun, "/dev/actk");
+		if(rc2 != 0)
+		{
+			VLDBG("open /dev/actk error:%d\n",__LINE__);
+			/*return rc2;*/
+		}
+		size = (int)curlun->num_sectors;
+		printk("##udisk size:%d    0x%x\n",size,size);
+	}	
+		
+	amount_left = fsg->data_size_from_cmnd;
+
+	if (unlikely(amount_left == 0))
+	{
+		return -EIO;	/* No default reply */
+	}
+
+	for (;;) {
+		amount = (unsigned int)amount_left;
+		/* Wait for the next buffer to become available */
+		bh = fsg->next_buffhd_to_fill;
+		while (bh->state != BUF_STATE_EMPTY) {
+			rc = sleep_thread(fsg);
+			if (rc)
+			{
+				return rc;
+			}
+		}
+		/* Perform the read */
+		memset((char *)bh->buf, 0, amount);
+		if(check_partition_flag < 0)
+		{
+			tmp = (unsigned int)bh->buf;
+			writel(-check_partition_flag, (volatile void *)tmp);			
+		}
+
+		//add partition cap info
+		memcpy((unsigned char *)((unsigned int)bh->buf + 0x10), (unsigned char *)&size, sizeof(unsigned int));
+		nread = amount;
+
+		amount_left -= (unsigned int)nread;
+		fsg->residue -= (unsigned int)nread;
+		bh->inreq->length = (unsigned int)nread;
+		bh->state = BUF_STATE_FULL;
+
+		if (amount_left == 0)
+			break;	/* No more left to read */
+
+		/* Send this buffer and go read some more */
+		bh->inreq->zero = 0;
+		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+			       &bh->inreq_busy, &bh->state);
+		fsg->next_buffhd_to_fill = bh->next;
+	}
+	no_finish_reply = 0;	/* the last buf has not been transfered,
+				   move it into finish_reply() */	   
+
+	return -EIO;		/* No default reply */
+}
+
+#define FLASH_READ_BUF_SECTORS (32)
+#define FLASH_READ_BUF_SIZE (FLASH_READ_BUF_SECTORS*512)
+unsigned int image_sectors, check_image_sectors;
+struct uparam read_param;
+
+#if 0
+static int do_ADFU_check_image_checksum(struct fsg_dev *fsg)
+{
+	/*struct lun *curlun = fsg->curlun;*/
+	struct fsg_buffhd *bh;
+	int rc;
+	u32 amount_left;
+	unsigned int amount;
+	ssize_t nread;
+	
+	int read_err=0;
+	unsigned int tmp;
+	unsigned int file_offset=0,read_sectors=0;
+       void *buf ;
+       
+	//Don't check phy_boot_partition 			
+	if(read_param.flash_partition == 0)
+	{
+		goto finish_check;	
+	}
+	
+	read_param.flash_partition -= 1;
+	read_param.devnum_in_phypart -= 1;
+	
+	buf= kmalloc(FLASH_READ_BUF_SIZE, GFP_KERNEL);
+	
+	for(;;)
+	{
+		if(check_image_sectors == 0)
+		{
+			break;
+		}		
+		if(check_image_sectors>FLASH_READ_BUF_SECTORS)
+		{
+			read_sectors = FLASH_READ_BUF_SECTORS;
+		}
+		else
+		{
+			read_sectors = check_image_sectors;
+		}
+
+//		printk("nand_read:0x%x,0x%x,%d,%d\n", file_offset, read_sectors, read_param.flash_partition, read_param.devnum_in_phypart);
+		read_err = adfus_nand_read(file_offset, read_sectors,
+					buf, &read_param);
+		//read_err = vfs_read(curlun->filp, buf, read_sectors << 9, &file_offset);
+		if(read_err < 0)
+		{
+			break;
+		}					
+		file_offset += read_sectors;					
+		check_image_sectors -= read_sectors;		
+	}
+	
+	kfree(buf);
+	buf=NULL;
+
+finish_check:
+						
+	amount_left = fsg->data_size_from_cmnd;
+
+	if (unlikely(amount_left == 0))
+	{
+		return -EIO;	/* No default reply */
+	}
+
+	for (;;) {
+		amount = (unsigned int)amount_left;
+		/* Wait for the next buffer to become available */
+		bh = fsg->next_buffhd_to_fill;
+		while (bh->state != BUF_STATE_EMPTY) {
+			rc = sleep_thread(fsg);
+			if (rc)
+			{
+				return rc;
+			}
+		}
+		/* Perform the read */
+		memset((char *)bh->buf, 0, amount);
+		if(read_err < 0)
+		{
+			tmp = (unsigned int)bh->buf;
+			writel(1,(volatile void *)tmp);			
+		}
+		nread = amount;
+
+		amount_left -= (unsigned int)nread;
+		fsg->residue -= (unsigned int)nread;
+		bh->inreq->length = (unsigned int)nread;
+		bh->state = BUF_STATE_FULL;
+
+		if (amount_left == 0)
+			break;	/* No more left to read */
+
+		/* Send this buffer and go read some more */
+		bh->inreq->zero = 0;
+		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+			       &bh->inreq_busy, &bh->state);
+		fsg->next_buffhd_to_fill = bh->next;
+	}
+	no_finish_reply = 0;	/* the last buf has not been transfered,
+				   move it into finish_reply() */
+	return -EIO;		/* No default reply */
+}
+#endif
+
+int do_ADFU_INFO(struct fsg_dev *fsg)
+{
+	int ret=0;
+	struct timeval tv1,tv2;
+	
+	switch(fsg->cmnd[2])
+	{
+		case 0x20:
+			ret = do_ADFU_check_partition(fsg);
+			break;
+		case 0x21:
+			do_gettimeofday(&tv1);
+			//ret = do_ADFU_check_image_checksum(fsg);
+			do_gettimeofday(&tv2);
+			printk("do_ADFU_check_image_checksum,timing:%ds\n",(int)(tv2.tv_sec-tv1.tv_sec));
+			break;
+		default:
+			break;
+	}
+	return ret;
+}
+
+int write_ram_bin(u32 addr, char *buf, u32 len)
+{
+	int ret=0;
+	char ram_bin_name[64];
+	static struct file *ram_bin_filp;
+	 loff_t file_offset_byte;
+	static int off_set;
+	int i;
+	char p[32];
+	int j,num1,num2;
+	num1=0;
+	num2=0;
+	
+	if ( buf == NULL ) {
+		if ( ram_bin_filp != NULL ) {			
+			filp_close(ram_bin_filp, current->files);
+			printk("write_ram_bin, finished, len=0x%x\n", off_set);
+			ram_bin_filp = NULL;
+		}
+		return 0;
+	}
+	
+	memset(ram_bin_name, 0, 64);
+	strcpy(ram_bin_name, "/usr/");
+	
+	if(addr == 0x21340000)
+	{
+		strcat(ram_bin_name, "mbrec.bin");		
+	}
+	else if(addr == 0x21340001)
+	{
+		strcat(ram_bin_name, "oem.ko");
+	}
+	else if(addr == 0x21350000)
+	{
+		printk("receive afinfo_name \n");
+		j=0;
+		for (i=0;i<32;i++)
+		{
+		 	afinfo_name[i]= readw((volatile void *)buf+i*2);
+			if( afinfo_name[i] == '.')
+			{
+				if(j==0)
+				{
+					num1=i;
+					j++;
+				}
+				else
+				{
+					num2=i;
+				}
+			}
+				
+		}
+		printk("afinfo_name:%s\n", afinfo_name);
+		printk("num1=%d, num2=%d\n", num1,num2);
+		if (num1==num2)
+		{
+			strcpy(mbrc_name,"nand-boot.bin");
+		}
+		else
+		{
+			for(i=num1+1,j=0;i<num2;i++,j++)
+			{
+				p[j]=afinfo_name[i];
+			}
+			p[j]='\0';
+			strcpy(mbrc_name,"nand-boot.");
+			strcat(mbrc_name,p);
+			strcat(mbrc_name,".bin");
+		}
+		printk("mbrc_name:%s\n", mbrc_name);
+		return 0;
+	}
+	else if(addr == 0x32140000)
+	{
+		strcat(ram_bin_name, "mbr_info.bin");
+		mbr_info_buf = kmalloc(1024, GFP_KERNEL);
+		memcpy(mbr_info_buf, buf, len);
+		need_format = readb((volatile void *)buf + 0x04);
+		printk("need_format:%d\n", need_format);
+	}
+	else if (addr == 0x32170000) { //checksum_system.bin
+		system_checksum = readl((volatile void *)buf);
+		printk("system checksum: 0x%08X\n", system_checksum);
+		return 0;
+	}
+	else if (addr == 0x32160000) { //checksum_recovery.bin
+		recovery_checksum = readl((volatile void *)buf);
+		printk("recovery checksum: 0x%08X\n", recovery_checksum);
+		return 0;
+	}
+	else if (addr == 0x32150000) { //checksum_misc.bin
+		misc_checksum = readl((volatile void *)buf);
+		printk("misc checksum: 0x%08X\n", misc_checksum);
+		return 0;
+	}
+	else
+	{
+		strcat(ram_bin_name, "afinfo.bin");
+		printk("need_checksum:%d\n", need_checksum);
+		need_format = readb((volatile void *)buf + 0x10);
+		need_restart = readb((volatile void *)buf + 0x11);
+		need_checksum = readb((volatile void *)buf + 0x09);
+		printk("need_format:%d\n", need_format);			
+		printk("need_restart:%d\n", need_restart);
+		printk("need_checksum:%d\n", need_checksum);
+	}
+	printk("addr:0x%x, ram_bin_name:%s, len=0x%x\n", addr, ram_bin_name, len);
+			
+	if(!ram_bin_filp)
+	{
+		off_set = 0;
+		ram_bin_filp = filp_open(ram_bin_name, O_WRONLY|O_CREAT, 0700);
+		if(!ram_bin_filp)
+		{
+			printk("fail to creat %s,errno:%p\n", ram_bin_name, ram_bin_filp);
+			ret = -1;
+			goto out;
+		}
+		else
+		{
+			printk("creat %s,filp:%p\n", ram_bin_name, ram_bin_filp);
+		}
+	}	
+	file_offset_byte = off_set;
+	ret = vfs_write(ram_bin_filp, buf, len, &file_offset_byte);	
+	printk("wr:len=0x%x, ret=0x%x, of=0x%x\n", len,ret,off_set);
+	off_set += ret;
+out:	
+	return ret;	
+}
+
+static int do_ADFU_access_iram(struct fsg_dev *fsg)
+{
+	struct lun *curlun = fsg->curlun;
+	struct fsg_buffhd *bh;
+	int get_some_more;
+	u32 amount_left_to_req, amount_left_to_write,download_addr;
+
+	unsigned int amount;
+	ssize_t nwritten;
+	int rc;
+
+	if (curlun->ro) {
+		curlun->sense_data = SS_WRITE_PROTECTED;
+		printk("return:%d\n",__LINE__);
+		return -EINVAL;
+	}
+
+	download_addr = get_le32(&fsg->cmnd[9]);
+	/* Carry out the file writes */
+	get_some_more = 1;
+	amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
+
+	printk("write ram len=0x%x\n", amount_left_to_req);
+	while (amount_left_to_write > 0) {
+
+		/* Queue a request for more data from the host */
+		bh = fsg->next_buffhd_to_fill;
+		if (bh->state == BUF_STATE_EMPTY && get_some_more) {
+
+			/* Figure out how much we want to get:
+			 * Try to get the remaining amount.
+			 * But don't get more than the buffer size.
+			 * And don't try to go past the end of the file.
+			 * If we're not at a page boundary,
+			 *      don't go past the next page.
+			 * If this means getting 0, then we were asked
+			 *      to write past the end of file.
+			 * Finally, round down to a block boundary. */
+			amount = min(amount_left_to_req, mod_data.buflen);
+			
+
+			/* Get the next buffer */
+			fsg->usb_amount_left -= amount;
+			amount_left_to_req -= amount;
+			if (amount_left_to_req == 0)
+				get_some_more = 0;
+
+			/* Except at the end of the transfer, amount will be
+			 * equal to the buffer size, which is divisible by
+			 * the bulk-out maxpacket size.
+			 */
+			set_bulk_out_req_length(fsg, bh, amount);
+			start_transfer(fsg, fsg->bulk_out, bh->outreq,
+				       &bh->outreq_busy, &bh->state);
+			fsg->next_buffhd_to_fill = bh->next;
+			continue;
+		}
+
+		/* Write the received data to the backing file */
+		bh = fsg->next_buffhd_to_drain;
+		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
+		{
+			VLDBG("break:%d,bh->state:%d, BUF_STATE_EMPTY:%d\n",__LINE__, bh->state, BUF_STATE_EMPTY);
+			break;	/* We stopped early */
+		}
+
+		if (bh->state == BUF_STATE_FULL) {
+			smp_rmb();
+			fsg->next_buffhd_to_drain = bh->next;
+			bh->state = BUF_STATE_EMPTY;
+
+			/* Did something go wrong with the transfer? */
+			if (bh->outreq->status != 0) {
+				curlun->sense_data = SS_COMMUNICATION_FAILURE;
+				curlun->info_valid = 1;
+				VLDBG("break:%d,bh->outreq->status:%d\n",__LINE__, bh->outreq->status);
+				break;
+			}
+
+			amount = bh->outreq->actual; /* unit by sector */
+			
+			/* Don't accept excess data.  The spec doesn't say
+			 * what to do in this case.  We'll ignore the error.
+			 */
+			amount = min(amount, bh->bulk_out_intended_length);
+			//amount = round_down(amount, curlun->blksize);
+			/* Perform the write */		
+			nwritten = write_ram_bin(download_addr, bh->buf, amount);
+			if(nwritten >= 0)
+			{
+				nwritten = amount;
+			}
+
+			if (signal_pending(current)) {
+				printk("return:%d\n",__LINE__);
+				return -EINTR;	/* Interrupted! */
+			}
+			if (nwritten < 0) {
+				LDBG(curlun, "error in file write: %d\n",
+				     (int)nwritten);
+				nwritten = 0;
+			} else if (nwritten < amount) {
+				LDBG(curlun, "partial file write: %d/%u\n",
+				     (int)nwritten, amount);
+				/* Round down to a block */
+			}
+			amount_left_to_write -= nwritten;
+			fsg->residue -= nwritten;
+
+			/* If an error occurred, report it and its position */
+			if (nwritten < amount) {
+				curlun->sense_data = SS_WRITE_ERROR;
+				curlun->info_valid = 1;
+				VLDBG("break:%d\n",__LINE__);
+				break;
+			}
+
+			/* Did the host decide to stop early? */
+			if (bh->outreq->actual != bh->outreq->length) {
+				fsg->short_packet_received = 1;
+				VLDBG("break:%d\n",__LINE__);
+				break;
+			}
+			continue;
+		}
+		else
+		{
+			VLDBG("break:%d,bh->state:%d\n",__LINE__, bh->state);
+		}
+
+		/* Wait for something to happen */
+		rc = sleep_thread(fsg);
+		if (rc) {
+			printk("return:%d\n",__LINE__);
+			return rc;
+		}
+	}
+	if(amount_left_to_write == 0) {
+		printk("write ram finished:\n");
+		write_ram_bin(0, NULL, 0); // finshed
+	}
+	no_finish_reply = 1;
+	printk("return:%d\n",__LINE__);
+	return -EIO;		/* No default reply */
+}
+
+char write_file_name[32];
+struct file *write_file_fp = NULL;
+loff_t pos = 0;
+static int do_ADFU_wtrootfs(struct fsg_dev *fsg)
+{
+	struct lun *curlun = fsg->curlun;
+	u32 lba;
+	struct fsg_buffhd *bh;
+	int get_some_more;
+	u32 amount_left_to_req, amount_left_to_write;
+	loff_t usb_offset, file_offset, file_offset_tmp;
+	struct uparam wt_param;
+	unsigned int amount;
+	ssize_t nwritten;
+	int rc;
+	char op_type;
+	int fs_len;
+	int i, error;
+
+
+	if (curlun->ro) {
+		curlun->sense_data = SS_WRITE_PROTECTED;
+		printk("return:%d\n",__LINE__);
+		return -EINVAL;
+	}
+
+
+	/* Get the starting Logical Block Address and check that it's
+	 * not too big */
+	lba = get_le32(&fsg->cmnd[9]);
+	wt_param.flash_partition = fsg->cmnd[2] & ~0x80;
+	wt_param.devnum_in_phypart = fsg->cmnd[2] & ~0x80;
+	
+	if(wt_param.flash_partition == 0x0 || wt_param.flash_partition == 0x1)
+	{
+		if (!write_file_fp)
+		{
+			//unit of probatch tool download img is 10MB
+			if (wt_param.flash_partition == 0x0 ) {
+				printk("write mbrec.bin\n");	
+				strcpy(write_file_name, "/tmp/mbrec.bin");
+			} else {
+				printk("write uboot.bin\n");	
+				strcpy(write_file_name, "/tmp/uboot.bin");			
+			}
+			write_file_fp = filp_open(write_file_name, O_RDWR | O_CREAT, 0644);
+			printk("boot:%s\n", write_file_name);
+			update_phy_boot = 1;
+		}
+
+	} else  {
+		//if(wt_param.flash_partition != UDISK_ACCESS)
+		//{
+		   wt_param.flash_partition -= 2;
+		   wt_param.devnum_in_phypart -= 2;
+		//}
+		printk("flash_partition:%d, devnum_in_phypart:%d\n", wt_param.flash_partition, wt_param.devnum_in_phypart);
+		sprintf(format_disk_name, "/dev/act%c", 'a'+wt_param.flash_partition);
+		printk("disk_name = %s\n", format_disk_name);
+	}
+ 
+
+	op_type = fsg->cmnd[3];
+	if(op_type == 1)
+	{
+		fs_len = fsg->cmnd[4];
+		memcpy(format_fs_name, &(fsg->cmnd[5]), fs_len);
+		format_fs_name[fs_len]=0;
+		for(i=0; i<fs_len; i++)
+		{
+			format_fs_name[i] = tolower(format_fs_name[i]);
+		}
+		//sprintf(format_disk_name, "/dev/act%c", 'a'+wt_param.flash_partition);
+		if ( wt_param.flash_partition >=3 && wt_param.flash_partition < 6 )
+			format_disk_label = disk_label[wt_param.flash_partition-3];
+		else
+			format_disk_label = disk_label[3];
+		printk("format:fs_name:%s, disk_name:%s, disk_label:%s\n", format_fs_name, format_disk_name, format_disk_label);
+		
+		set_probatch_phase(PROBATCH_FORMAT);
+		wait_adfus_proc(PROBATCH_FINISH_FORMAT);//sync with upgrade_app	
+		goto out;
+	}
+	
+	/* Carry out the file writes */
+	get_some_more = 1;
+	usb_offset = ((loff_t) lba) << 9;
+	file_offset = lba;  /* unit by sector */
+	amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
+	printk("w(sector):len=0x%x, offset=0x%x\n", amount_left_to_write, lba);
+	/*changed by liyong, to add a file operation to write flash*/
+	if(!write_file_fp) { 
+		write_file_fp = filp_open(format_disk_name, O_RDWR, 0644);
+		error = PTR_ERR(write_file_fp);
+		if(IS_ERR(write_file_fp)) {
+				printk("open %s error ,error = %d\n", format_disk_name, error);	
+				return -1;	
+		}
+	}
+	
+	if(amount_left_to_write == 0)
+	{
+		read_param.flash_partition = fsg->cmnd[2] & ~0x80;
+		read_param.devnum_in_phypart = fsg->cmnd[2] & ~0x80;
+		printk("image_sectors:0x%x,%d,%d\n", image_sectors, read_param.flash_partition, read_param.devnum_in_phypart);	
+		check_image_sectors = image_sectors;
+		image_sectors = 0;
+		if(write_file_fp)
+		{
+			filp_close(write_file_fp, current->files);
+			write_file_fp = NULL;
+			pos = 0;
+			write_file_name[0] = 0;
+		}		
+		goto out;
+	}
+	image_sectors += amount_left_to_write>>9;	
+	while (amount_left_to_write > 0) {
+
+		/* Queue a request for more data from the host */
+		bh = fsg->next_buffhd_to_fill;
+		if (bh->state == BUF_STATE_EMPTY && get_some_more) {
+
+			/* Figure out how much we want to get:
+			 * Try to get the remaining amount.
+			 * But don't get more than the buffer size.
+			 * And don't try to go past the end of the file.
+			 * If we're not at a page boundary,
+			 *      don't go past the next page.
+			 * If this means getting 0, then we were asked
+			 *      to write past the end of file.
+			 * Finally, round down to a block boundary. */
+			amount = min(amount_left_to_req, mod_data.buflen);
+			/*
+			amount = min((loff_t) amount, curlun->file_length -
+				     usb_offset);
+			*/
+
+			/* move the overflow judge into flash driver? */
+
+			/*
+			partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
+			if (partial_page > 0)
+				amount = min(amount,
+					     (unsigned int)PAGE_CACHE_SIZE -
+					     partial_page);
+			if (amount == 0) {
+				get_some_more = 0;
+				curlun->sense_data =
+				    SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+				curlun->sense_data_info = usb_offset >> 9;
+				curlun->info_valid = 1;
+				continue;
+			}
+			*/
+
+
+			/* Get the next buffer */
+			usb_offset += amount;  /* for future use(test the boundary) */
+			fsg->usb_amount_left -= amount;
+			amount_left_to_req -= amount;
+			if (amount_left_to_req == 0)
+				get_some_more = 0;
+
+			/* Except at the end of the transfer, amount will be
+			 * equal to the buffer size, which is divisible by
+			 * the bulk-out maxpacket size.
+			 */
+			set_bulk_out_req_length(fsg, bh, amount);
+			start_transfer(fsg, fsg->bulk_out, bh->outreq,
+				       &bh->outreq_busy, &bh->state);
+			fsg->next_buffhd_to_fill = bh->next;
+
+			continue;
+		}
+
+		/* Write the received data to the backing file */
+		bh = fsg->next_buffhd_to_drain;
+		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
+		{
+			VLDBG("break:%d,bh->state:%d, BUF_STATE_EMPTY:%d\n",__LINE__, bh->state, BUF_STATE_EMPTY);
+			break;	/* We stopped early */
+		}
+
+		if (bh->state == BUF_STATE_FULL) {
+			smp_rmb();
+			fsg->next_buffhd_to_drain = bh->next;
+			bh->state = BUF_STATE_EMPTY;
+
+			/* Did something go wrong with the transfer? */
+			if (bh->outreq->status != 0) {
+				curlun->sense_data = SS_COMMUNICATION_FAILURE;
+				curlun->sense_data_info = file_offset;
+				curlun->info_valid = 1;
+				VLDBG("break:%d,bh->outreq->status:%d\n",__LINE__, bh->outreq->status);
+				break;
+			}
+
+			amount = bh->outreq->actual; /* unit by sector */
+			
+			/* Don't accept excess data.  The spec doesn't say
+			 * what to do in this case.  We'll ignore the error.
+			 */
+			amount = min(amount, bh->bulk_out_intended_length);
+			//amount = round_down(amount, curlun->blksize);
+
+			/* Perform the write */
+			file_offset_tmp = file_offset;
+
+			VLDBG("Perform the write,wt_param.devnum_in_phypart:0x%x\n", wt_param.devnum_in_phypart);		
+//			if(wt_param.devnum_in_phypart == 0x1)
+			{
+
+				if(!write_file_fp)
+				{
+					
+					//nwritten = adfus_nand_write(file_offset, amount >> 9,
+						//bh->buf, &wt_param);
+					//printk("===================== flip:0x%x, buf:0x%x, amount:0x%x,offset:0x%x\n",curlun->filp,bh->buf, amount >> 9, file_offset_tmp);
+					//nwritten = vfs_write(curlun->filp,bh->buf, amount, &file_offset_tmp);
+					//nwritten = nwritten << 9;	
+					//VLDBG("amount:0x%x,nwritten:0x%x,file_offset:0x%x\n", amount, nwritten, (unsigned long)file_offset);		
+					nwritten = 0;
+				}
+				else {
+					//printk("amount:0x%x,nwritten:0x%x,pos:0x%x\n", amount, nwritten, (unsigned long)pos);
+					/* reinitialize offset for random write */
+					pos = file_offset << 9;
+					//printk("startw: wlen=0x%x,pos:0x%x\n", amount, (unsigned long)pos);
+					nwritten = write_file_fp->f_op->write(write_file_fp, bh->buf, amount, &pos);
+					//printk("endw: wlen=0x%x\n", nwritten);
+				}	
+			}
+			
+			if (signal_pending(current)) {
+				printk("return:%d\n",__LINE__);
+				return -EINTR;	/* Interrupted! */
+			}
+			if (nwritten < 0) {
+				LDBG(curlun, "error in file write: %d\n",
+				     (int)nwritten);
+				nwritten = 0;
+			} else if (nwritten < amount) {
+				LDBG(curlun, "partial file write: %d/%u\n",
+				     (int)nwritten, amount);
+				/* Round down to a block */
+			}
+			file_offset += nwritten >> 9;
+			amount_left_to_write -= nwritten;
+			fsg->residue -= nwritten;
+
+			/* If an error occurred, report it and its position */
+			if (nwritten < amount) {
+				curlun->sense_data = SS_WRITE_ERROR;
+				curlun->sense_data_info = file_offset;
+				curlun->info_valid = 1;
+				VLDBG("break:%d\n",__LINE__);
+				break;
+			}
+
+			/* Did the host decide to stop early? */
+			if (bh->outreq->actual != bh->outreq->length) {
+				fsg->short_packet_received = 1;
+				VLDBG("break:%d\n",__LINE__);
+				break;
+			}
+			continue;
+		}
+		else
+		{
+			VLDBG("break:%d,bh->state:%d\n",__LINE__, bh->state);
+		}
+
+		/* Wait for something to happen */
+		rc = sleep_thread(fsg);
+		if (rc) {
+			VLDBG("return:%d\n",__LINE__);
+			return rc;
+		}
+	}
+
+out:
+	no_finish_reply = 1;
+	VLDBG("return:%d\n",__LINE__);
+	return -EIO;		/* No default reply */
+}
+
+/* Sync the file data, don't bother with the metadata.
+ * This code was copied from fs/buffer.c:sys_fdatasync(). */
+static int fsync_sub(struct lun *curlun)
+{
+#if 0
+	if (curlun->disk_type == NAND_MEDIUM)
+	{
+		dev_t media_dev_t;
+		struct gendisk *disk;
+		struct block_device *bdev_back;
+		media_dev_t = curlun->devnum;
+		bdev_back = bdget(media_dev_t);
+		disk = bdev_back->bd_disk;
+			
+		if (disk == NULL)
+		{ 
+			bdput(bdev_back);
+			return 0;
+		}
+		if (disk->fops->flush_disk_cache != NULL) {
+			disk->fops->flush_disk_cache();
+		}
+		bdput(bdev_back);
+	}
+	return 0;	//when we dont use VFS, we neednt sync
+#else
+	struct file	*filp = curlun->filp;
+
+	if (curlun->ro || !filp)
+		return 0;
+	return vfs_fsync(filp, 1);
+
+#endif
+}
+
+static void fsync_all(struct fsg_dev *fsg)
+{
+	int i;
+
+	for (i = 0; i < fsg->nluns; ++i)
+		fsync_sub(&fsg->luns[i]);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
+{
+	int rc;
+	rc = fsg_set_halt(fsg, fsg->bulk_in);
+
+	if (rc == -EAGAIN)
+		VDBG(fsg, "delayed bulk-in endpoint halt\n");
+	while (rc != 0) {
+		if (rc != -EAGAIN) {
+			WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
+			rc = 0;
+			break;
+		}
+
+		/* Wait for a short time and then try again */
+		if (msleep_interruptible(100) != 0)
+			return -EINTR;
+		rc = usb_ep_set_halt(fsg->bulk_in);
+	}
+	return rc;
+}
+#if 0
+static int halt_bulk_out_endpoint(struct fsg_dev *fsg)
+{
+	int rc;
+	rc = fsg_set_halt(fsg, fsg->bulk_out);
+
+	if (rc == -EAGAIN)
+		VDBG(fsg, "delayed bulk-out endpoint halt\n");
+	while (rc != 0) {
+		if (rc != -EAGAIN) {
+			WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
+			rc = 0;
+			break;
+		}
+
+		/* Wait for a short time and then try again */
+		if (msleep_interruptible(100) != 0)
+			return -EINTR;
+		rc = usb_ep_set_halt(fsg->bulk_out);
+	}
+	return rc;
+}
+
+static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
+{
+	int rc;
+
+	DBG(fsg, "bulk-in set wedge\n");
+	rc = usb_ep_set_wedge(fsg->bulk_in);
+	if (rc == -EAGAIN)
+		VDBG(fsg, "delayed bulk-in endpoint wedge\n");
+	while (rc != 0) {
+		if (rc != -EAGAIN) {
+			WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
+			rc = 0;
+			break;
+		}
+
+		/* Wait for a short time and then try again */
+		if (msleep_interruptible(100) != 0)
+			return -EINTR;
+		rc = usb_ep_set_wedge(fsg->bulk_in);
+	}
+	return rc;
+}
+#endif
+static int pad_with_zeros(struct fsg_dev *fsg)
+{
+	struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
+	u32 nkeep = bh->inreq->length;
+	u32 nsend;
+	int rc;
+	bh->state = BUF_STATE_EMPTY;	/* For the first iteration */
+	fsg->usb_amount_left = nkeep + fsg->residue;
+	while (fsg->usb_amount_left > 0) {
+
+		/* Wait for the next buffer to be free */
+		while (bh->state != BUF_STATE_EMPTY) {
+			rc = sleep_thread(fsg);
+			if (rc)
+				return rc;
+
+		}
+
+		nsend = min(fsg->usb_amount_left, (u32) mod_data.buflen);
+		memset(bh->buf + nkeep, 0, nsend - nkeep);
+		bh->inreq->length = nsend;
+		bh->inreq->zero = 0;
+		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+			       &bh->inreq_busy, &bh->state);
+		bh = fsg->next_buffhd_to_fill = bh->next;
+		fsg->usb_amount_left -= nsend;
+		nkeep = 0;
+	}
+	return 0;
+}
+
+static int throw_away_data(struct fsg_dev *fsg)
+{
+	struct fsg_buffhd *bh;
+	u32 amount;
+	int rc;
+
+	while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
+	       fsg->usb_amount_left > 0) {
+
+		/* Throw away the data in a filled buffer */
+		if (bh->state == BUF_STATE_FULL) {
+			smp_rmb();
+			bh->state = BUF_STATE_EMPTY;
+			fsg->next_buffhd_to_drain = bh->next;
+
+			/* A short packet or an error ends everything */
+			if (bh->outreq->actual < bh->bulk_out_intended_length ||
+			    bh->outreq->status != 0) {
+				raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
+				return -EINTR;
+			}
+			continue;
+		}
+
+		/* Try to submit another request if we need one */
+		bh = fsg->next_buffhd_to_fill;
+		if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
+			amount = min(fsg->usb_amount_left,
+				     (u32) mod_data.buflen);
+
+			/* amount is always divisible by 512, hence by
+			 * the bulk-out maxpacket size */
+
+			set_bulk_out_req_length(fsg, bh, amount);
+			start_transfer(fsg, fsg->bulk_out, bh->outreq,
+				       &bh->outreq_busy, &bh->state);
+			fsg->next_buffhd_to_fill = bh->next;
+			fsg->usb_amount_left -= amount;
+			continue;
+		}
+
+		/* Otherwise wait for something to happen */
+		rc = sleep_thread(fsg);
+		if (rc)
+			return rc;
+
+	}
+	return 0;
+}
+
+extern int finish_reply(struct fsg_dev *fsg);
+int finish_reply(struct fsg_dev *fsg)
+{
+	struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
+	int rc = 0;
+
+	switch (fsg->data_dir) {
+	case DATA_DIR_NONE:
+		break;		/* Nothing to send */
+
+		/* If we don't know whether the host wants to read or write,
+		 * this must be CB or CBI with an unknown command.  We mustn't
+		 * try to send or receive any data.  So stall both bulk pipes
+		 * if we can and wait for a reset. */
+	case DATA_DIR_UNKNOWN:
+		if (mod_data.can_stall) {
+			fsg_set_halt(fsg, fsg->bulk_out);
+			rc = halt_bulk_in_endpoint(fsg);
+		}
+		break;
+
+	/* All but the last buffer of data must have already been sent */
+	case DATA_DIR_TO_HOST:
+		if (fsg->data_size == 0)
+			;	/* Nothing to send */
+
+		/* If there's no residue, simply send the last buffer */
+		else if (fsg->residue == 0) {
+			if (!no_finish_reply) {
+				bh->inreq->zero = 0;
+				/* bh->inreq->medium = 0; */
+				start_transfer(fsg, fsg->bulk_in,
+						bh->inreq,
+						&bh->inreq_busy,
+						&bh->state);
+				fsg->next_buffhd_to_fill = bh->next;
+			} else {
+				/* */
+				no_finish_reply = 0;
+			}
+		} else {
+#if 0
+			if (mod_data.can_stall) {
+				bh->inreq->zero = 1;
+				start_transfer(fsg, fsg->bulk_in, bh->inreq,
+						&bh->inreq_busy, &bh->state);
+				fsg->next_buffhd_to_fill = bh->next;
+				rc = halt_bulk_in_endpoint(fsg);
+			} else
+#endif
+				rc = pad_with_zeros(fsg);
+		}
+
+		break;
+
+		/* We have processed all we want
+		 * from the data the host has sent.
+		 * There may still be outstanding bulk-out requests. */
+	case DATA_DIR_FROM_HOST:
+		if ((fsg->residue == 0) || (no_finish_reply))
+			no_finish_reply = 0;	/* Nothing to receive */
+
+		/* Did the host stop sending unexpectedly early? */
+		else if (fsg->short_packet_received) {
+			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
+			rc = -EINTR;
+		}
+
+		/* We haven't processed all the incoming data.  Even though
+		 * we may be allowed to stall, doing so would cause a race.
+		 * The controller may already have ACK'ed all the remaining
+		 * bulk-out packets, in which case the host wouldn't see a
+		 * STALL.  Not realizing the endpoint was halted, it wouldn't
+		 * clear the halt -- leading to problems later on. */
+#if 0
+		else if (mod_data.can_stall) {
+			fsg_set_halt(fsg, fsg->bulk_out);
+			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
+			rc = -EINTR;
+		}
+#endif
+		else
+			rc = throw_away_data(fsg);
+
+		/* We can't stall.  Read in the excess data and throw it
+		 * all away. */
+		break;
+	}
+	return rc;
+}
+#if 0
+u32 get_phBaseAddr(void)
+{
+	u32 tmp;
+	
+	__asm__ __volatile__ ("mrc p15, 4, %0, c15, c0, 0":"=r"(tmp));
+	return tmp;
+}
+
+// void init_WD_timer(unsigned int load_value, unsigned int auto_reload)
+// Sets up the WD timer
+// r0: initial load value
+// r1:  IF 0 (AutoReload) ELSE (SingleShot)
+void init_WD_timer(unsigned int load_value, unsigned int auto_reload)
+{
+	u32 phBaseAddr, wdCountAddr, wdModeAddr, tmp=0;
+   	
+   	phBaseAddr = get_phBaseAddr();
+   	wdCountAddr = phBaseAddr+0x620;
+   	wdModeAddr = phBaseAddr+0x628;
+   	
+    	writel(load_value, (volatile void *)wdCountAddr);
+   	if(auto_reload == 0)
+   	{
+   		tmp = 0x2;	
+   	}
+   	writel(tmp, (volatile void *)wdModeAddr);
+}
+
+static void WD_is_running(void)
+{
+	u32 phBaseAddr, wdModeAddr;
+
+	phBaseAddr = get_phBaseAddr();
+   	wdModeAddr = phBaseAddr+0x628;
+
+    if (readl(wdModeAddr) & 0x8)
+        return ;
+
+    return ;
+}
+
+static void clear_is_running(void)
+{
+	u32 phBaseAddr, wdModeAddr;
+
+	phBaseAddr = get_phBaseAddr();
+   	wdModeAddr = phBaseAddr+0x628;
+
+    if (readl(wdModeAddr) & 0x8)
+        return ;
+
+    return ;
+}
+
+extern struct atc260x_dev *atc260x_dev_handle;
+
+static void clear_enteradfu_flag(void)
+{
+    atc260x_set_bits(atc260x_dev_handle, atc2603_PMU_UV_INT_EN, 0x2 , 0x0);
+    mdelay(1);
+    printk(KERN_INFO "atc2603_PMU_UV_INT_EN: %x\n", atc260x_reg_read(atc260x_dev_handle, atc2603_PMU_UV_INT_EN));
+}
+
+static int need_enteradfu(void)
+{
+    return (atc260x_reg_read(atc260x_dev_handle, atc2603_PMU_UV_INT_EN) & 0x2) ? 1 : 0;
+}
+#endif
+
+// void set_WD_mode(unsigned int mode)
+// Sets up the WD timer  
+// r0:  IF 0 (timer mode) ELSE (watchdog mode)
+//	void set_WD_mode(unsigned int mode)
+//	{
+//		u32 phBaseAddr, wdModeAddr;
+//		
+//		phBaseAddr = get_phBaseAddr();
+//	   	wdModeAddr = phBaseAddr+0x628;
+//	   	
+//	   	if(mode == 0)
+//	   	{
+//	   		writel((readl(wdModeAddr) & 0xf7) | 0x4, wdModeAddr);
+//	   	}
+//	   	else
+//	   	{
+//	   		writel(readl(wdModeAddr) | 0x8, wdModeAddr);
+//	   	}
+//	}
+//	
+//	void start_WD_timer(void)
+//	{
+//		u32 phBaseAddr, wdModeAddr;
+//		
+//		phBaseAddr = get_phBaseAddr();
+//	   	wdModeAddr = phBaseAddr+0x628;
+//	   	
+//		writel(readl(wdModeAddr) | 0x1, wdModeAddr);
+//	}
+//	
+//	int wd_restart(void)
+//	{
+//	    printk(KERN_INFO "wd_restart\n");
+//	
+//	    if (need_enteradfu())
+//	    {
+//	        printk(KERN_INFO "clear enter adfu flag\n");
+//	        clear_enteradfu_flag();
+//	    }
+//	
+//	    msleep(10);
+//	
+//		//bit26=1,ʹWD0\B8\B4λ\CB\F9\D3\D0cpu\BC\B0\D5\FB\B8\F6ϵͳ(\B3\FD\C1˸\C3bit\BA\CDWDRESET0)\A3\AC\C6\E4\CB\FC\BCĴ\E6\C6\F7ȫ\B2\BF\B8\B4λ
+//	    writel(readl(SPS_PG_CTL)|0x04000000, SPS_PG_CTL);
+//	    init_WD_timer(0x98, 0x01);
+//	    set_WD_mode(1);
+//	    start_WD_timer();
+//	    while(1)
+//	    {
+//	    };
+//	}
+
+//extern unsigned long (*boot_info_read)(unsigned long);
+//extern int (*boot_info_write)(unsigned long, unsigned long);
+static int send_status(struct fsg_dev *fsg)
+{
+	struct lun *curlun = fsg->curlun;
+	struct fsg_buffhd *bh;
+	int rc;
+	u8 status = USB_STATUS_PASS;
+	u32 sd, sdinfo = 0;
+	/* Wait for the next buffer to become available */
+	bh = fsg->next_buffhd_to_fill;
+	while (bh->state != BUF_STATE_EMPTY) {
+		rc = sleep_thread(fsg);
+		if (rc)
+			return rc;
+
+	}
+	if (curlun) {
+		sd = curlun->sense_data;
+		sdinfo = curlun->sense_data_info;
+	} else if (fsg->bad_lun_okay)
+		sd = SS_NO_SENSE;
+	else
+		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
+
+	if (fsg->phase_error) {
+		DBG(fsg, "sending phase-error status\n");
+		status = USB_STATUS_PHASE_ERROR;
+		sd = SS_INVALID_COMMAND;
+	} else if (sd != SS_NO_SENSE) {
+		DBG(fsg, "sending command-failure status\n");
+		status = USB_STATUS_FAIL;
+		VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
+		     "  info x%x\n", SK(sd), ASC(sd), ASCQ(sd), sdinfo);
+	}
+	if (transport_is_bbb()) {
+		struct bulk_cs_wrap *csw = bh->buf;
+
+		/* Store and send the Bulk-only CSW */
+		csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
+		csw->Tag = fsg->tag;
+		csw->Residue = cpu_to_le32(fsg->residue);
+		csw->Status = status;
+#if 0
+		printk(KERN_INFO
+			"csw-> SIG: %x Tag:%x Residue:%x Status:%x\n",
+		       csw->Signature, csw->Tag, csw->Residue, csw->Status);
+#endif
+		bh->inreq->length = USB_BULK_CS_WRAP_LEN;
+		bh->inreq->zero = 0;
+		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+			       &bh->inreq_busy, &bh->state);
+
+	} else if (mod_data.transport_type == USB_PR_CB) {
+
+		/* Control-Bulk transport has no status phase! */
+		return 0;
+
+	} else {		/* USB_PR_CBI */
+		struct interrupt_data *buf = bh->buf;
+
+		/* Store and send the Interrupt data.  UFI sends the ASC
+		 * and ASCQ bytes.  Everything else sends a Type (which
+		 * is always 0) and the status Value. */
+		if (mod_data.protocol_type == USB_SC_UFI) {
+			buf->bType = ASC(sd);
+			buf->bValue = ASCQ(sd);
+		} else {
+			buf->bType = 0;
+			buf->bValue = status;
+		}
+		fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
+
+		fsg->intr_buffhd = bh;	/* Point to the right buffhd */
+		fsg->intreq->buf = bh->inreq->buf;
+		fsg->intreq->context = bh;
+		start_transfer(fsg, fsg->intr_in, fsg->intreq,
+			       &fsg->intreq_busy, &bh->state);
+	}
+
+	fsg->next_buffhd_to_fill = bh->next;
+
+//		/* when adfu upgrade successful, disconnect and sync */
+//		if (unlikely(adfu_success_flag == 1)) {
+//			raise_exception(fsg, FSG_STATE_DISCONNECT);
+//			adfu_flush_nand_cache();
+//			
+//			if (boot_info_write && boot_info_read) {
+//				boot_info_write(atc2603_PMU_SYS_CTL8, 0x0);
+//				boot_info_write(atc2603_PMU_SYS_CTL9, 0x0);
+//				printk("\n%s, %d, ctl8: %x, ctl9: %x\n", __func__, __LINE__, boot_info_read(atc2603_PMU_SYS_CTL8), boot_info_read(atc2603_PMU_SYS_CTL9));
+//			}
+//			
+//			printk(KERN_INFO "UPGRADE SUCCESSFULLY\n");
+//			if(need_restart == 0)
+//			{
+//				machine_restart("reboot");
+//			}
+//		}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Check whether the command is properly formed and whether its data size
+ * and direction agree with the values we already have. */
+static int check_command(struct fsg_dev *fsg, int cmnd_size,
+			 enum data_direction data_dir, unsigned int mask,
+			 int needs_medium, const char *name)
+{
+	//int i;
+	int lun = fsg->cmnd[1] >> 5;
+	static const char dirletter[4] = { 'u', 'o', 'i', 'n' };
+	char hdlen[20];
+	struct lun *curlun;
+
+
+	/* There's some disagreement as to whether RBC pads commands or not.
+	 * We'll play it safe and accept either form. */
+	if (mod_data.protocol_type == USB_SC_RBC) {
+		if (fsg->cmnd_size == 12)
+			cmnd_size = 12;
+
+		/* All the other protocols pad to 12 bytes */
+	} else
+		cmnd_size = 12;
+
+	hdlen[0] = 0;
+	if (fsg->data_dir != DATA_DIR_UNKNOWN)
+		sprintf(hdlen, ", H%c=%u", dirletter[(int)fsg->data_dir],
+			fsg->data_size);
+
+	VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
+	     name, cmnd_size, dirletter[(int)data_dir],
+	     fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
+
+	/* We can't reply at all until we know the correct data direction
+	 * and size. */
+	if (fsg->data_size_from_cmnd == 0)
+		data_dir = DATA_DIR_NONE;
+	if (fsg->data_dir == DATA_DIR_UNKNOWN) {	/* CB or CBI */
+		fsg->data_dir = data_dir;
+		fsg->data_size = fsg->data_size_from_cmnd;
+
+	} else {		/* Bulk-only */
+		if (fsg->data_size < fsg->data_size_from_cmnd) {
+
+			/* Host data size < Device data size is a phase error.
+			 * Carry out the command, but only transfer as much
+			 * as we are allowed. */
+			fsg->data_size_from_cmnd = fsg->data_size;
+			fsg->phase_error = 1;
+		}
+	}
+	fsg->residue = fsg->usb_amount_left = fsg->data_size;
+
+	/* Conflicting data directions is a phase error */
+	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
+		fsg->phase_error = 1;
+		return -EINVAL;
+	}
+#if 0
+	/* Verify the length of the command itself */
+	if (cmnd_size != fsg->cmnd_size) {
+
+		/* Special case workaround: There are plenty of buggy SCSI
+		 * implementations. Many have issues with cbw->Length
+		 * field passing a wrong command size. For those cases we
+		 * always try to work around the problem by using the length
+		 * sent by the host side provided it is at least as large
+		 * as the correct command length.
+		 * Examples of such cases would be MS-Windows, which issues
+		 * REQUEST SENSE with cbw->Length == 12 where it should
+		 * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
+		 * REQUEST SENSE with cbw->Length == 10 where it should
+		 * be 6 as well.
+		 */
+		if (cmnd_size <= fsg->cmnd_size) {
+			DBG(fsg, "%s is buggy! Expected length %d "
+			    "but we got %d\n", name, cmnd_size, fsg->cmnd_size);
+			cmnd_size = fsg->cmnd_size;
+		} else {
+			fsg->phase_error = 1;
+			return -EINVAL;
+		}
+	}
+#endif
+	/* Check that the LUN values are consistent */
+	if (transport_is_bbb()) {
+		if (fsg->lun != lun)
+			DBG(fsg, "using LUN %d from CBW, "
+			    "not LUN %d from CDB\n", fsg->lun, lun);
+	} else
+		fsg->lun = lun;	/* Use LUN from the command */
+
+	/* Check the LUN */
+	if (fsg->lun >= 0 && fsg->lun < fsg->nluns) {
+		fsg->curlun = curlun = &fsg->luns[fsg->lun];
+		if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
+			curlun->sense_data = SS_NO_SENSE;
+			curlun->sense_data_info = 0;
+			curlun->info_valid = 0;
+		}
+	} else {
+		fsg->curlun = curlun = NULL;
+		fsg->bad_lun_okay = 0;
+
+		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
+		 * to use unsupported LUNs; all others may not. */
+		if (fsg->cmnd[0] != SC_INQUIRY &&
+		    fsg->cmnd[0] != SC_REQUEST_SENSE) {
+			DBG(fsg, "unsupported LUN %d\n", fsg->lun);
+			return -EINVAL;
+		}
+	}
+
+	/* If a unit attention condition exists, only INQUIRY and
+	 * REQUEST SENSE commands are allowed; anything else must fail. */
+	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
+	    fsg->cmnd[0] != SC_INQUIRY && fsg->cmnd[0] != SC_REQUEST_SENSE) {
+		curlun->sense_data = curlun->unit_attention_data;
+		curlun->unit_attention_data = SS_NO_SENSE;
+		return -EINVAL;
+	}
+#if 0
+	/* Check that only command bytes listed in the mask are non-zero */
+	fsg->cmnd[1] &= 0x1f;	/* Mask away the LUN */
+	for (i = 1; i < cmnd_size; ++i) {
+		if (fsg->cmnd[i] && !(mask & (1 << i))) {
+			if (curlun)
+				curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
+			return -EINVAL;
+		}
+	}
+#endif
+	/* If the medium isn't mounted and the command needs to access
+	 * it, return an error. */
+	if (curlun && !backing_file_is_open(curlun) && needs_medium) {
+		curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int adfu_do_checksum(struct fsg_dev *fsg)
+{
+	struct file *filp_checksum_flash;
+	u32 checksum_flash;
+	loff_t offset_flash;
+	int checksum_ok = 0;
+	int must_checksum = 0;
+	int i;
+	
+
+	u32 *expect_checksum[] = {
+		&misc_checksum,
+		&recovery_checksum,
+		&system_checksum,
+	};
+
+	u32 *need_checksum_p[] = {
+		&write_mbrc,
+		&write_recovery,
+		&write_system,
+	};
+	const char *checksum_file_path[] = {
+		"/sys/block/acta/checksum",
+		"/sys/block/actb/checksum",
+		"/sys/block/actc/checksum",
+	};
+	const int checksum_count = ARRAY_SIZE(checksum_file_path);
+	
+	for (i = 0; i < checksum_count; i++) {
+		if ((*expect_checksum[i] != INVALID_ADFU_CHECKSUM)&& (*need_checksum_p[i] != 0) ){
+			must_checksum++;
+		}
+	}
+	
+	if (must_checksum == 0) {
+		pr_err("no checksum.bin ???\n");
+		//return -1;	
+	}
+
+	for (i = 0; i < checksum_count; i++) {
+		filp_checksum_flash = NULL;
+		checksum_flash = 0;
+		offset_flash = 0;
+
+		if (*expect_checksum[i] == INVALID_ADFU_CHECKSUM) {
+			continue;
+		}
+
+		if (*need_checksum_p[i] == 0) {
+			continue;
+		}
+
+		filp_checksum_flash = filp_open(checksum_file_path[i], O_RDONLY, 0);
+		if (IS_ERR(filp_checksum_flash)) {
+			pr_err("can not open [%s] , err %d.\n", checksum_file_path[i], (int)PTR_ERR(filp_checksum_flash));
+			continue;
+		}
+		else {
+			if (4 == vfs_read(filp_checksum_flash, (char __user *)&checksum_flash, 4, &offset_flash)) {
+				printk("checksum_flash = 0x%08X     expect_checksum[%d] = 0x%08X \n", checksum_flash, i , *expect_checksum[i]);
+				if (checksum_flash == *expect_checksum[i]) {
+					checksum_ok++;
+				}
+			}
+			else {
+				pr_err("read [%s] error.\n", checksum_file_path[i]);
+			}
+
+			filp_close(filp_checksum_flash, current->files);
+		}
+	}
+
+	if (checksum_ok == must_checksum)
+		return 0;
+
+	return -1;
+}
+
+static void adfu_sync_bdev(const char *path)
+{
+	struct file *filp;
+
+	pr_err("[adfuserver]sync .. bdev %s\n", path);
+
+	filp = filp_open(path, O_RDWR, 0);
+	if (IS_ERR(filp)) {
+		pr_err("can not open %s\n", path);
+		return;
+	}
+
+	vfs_fsync(filp, 1);
+	filp_close(filp, 0);
+}
+
+extern int do_scsi_command(struct fsg_dev *fsg);
+int do_scsi_command(struct fsg_dev *fsg)
+{
+	struct fsg_buffhd *bh;
+	int rc;
+	int reply = -EINVAL;
+	unsigned char sub_code;
+	static char unknown[16];
+	struct lun *curlun = fsg->curlun;
+
+	dump_cdb(fsg);
+
+	/* Wait for the next buffer to become available for data or status */
+	bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
+	while (bh->state != BUF_STATE_EMPTY) {
+		rc = sleep_thread(fsg);
+		if (rc)
+			return rc;
+	}
+	fsg->phase_error = 0;
+	fsg->short_packet_received = 0;
+
+	down_read(&fsg->filesem);	/* We're using the backing file */
+	printk("fsg->cmnd[0-2] = 0x%x 0x%x 0x%x\n", fsg->cmnd[0], fsg->cmnd[1], fsg->cmnd[2]);
+	switch (fsg->cmnd[0]) {
+
+	case SC_ADFU_UPGRADE:
+		/* printk(KERN_INFO "*******ADFU_UPGRADE_COMMAND:*******\n"); */
+		fsg->lun = 0; /* cheat the OS */
+		fsg->curlun = curlun = &fsg->luns[fsg->lun];
+		curlun->sense_data = SS_NO_SENSE;
+		curlun->sense_data_info = 0;
+		curlun->info_valid = 0;
+
+		sub_code = fsg->cmnd[1];
+		switch (sub_code) {
+
+//		case SC_ADFU_FORMAT_FLASH:
+//		printk(KERN_INFO "\n****** ERASE THE FLASH ******\n");
+//			need_format = 1;
+//			fsg->data_dir = DATA_DIR_NONE;
+//
+//			break;
+
+//		case SC_ADFU_TEST_FLASHRDY:
+//		/* printk(KERN_INFO "\n****** TEST FLASH ERASE READY ******\n"); */
+//			fsg->data_dir = DATA_DIR_NONE;
+//			if (!backing_file_is_open(curlun)) {
+//				/* printk(KERN_INFO "\n****** NOT READY ******\n"); */
+//				curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
+//			} else {
+//				/* */
+//				printk(KERN_INFO "\n****** READY ******\n");
+//			}
+//
+//			break;
+
+//		case SC_ADFU_ACCESS_MBR:
+//		/* printk(KERN_INFO "*******ACCESS THE MBR !!*******\n"); */
+//			fsg->data_size = 0x400;
+//			fsg->residue = fsg->usb_amount_left = fsg->data_size;
+//			fsg->data_dir = DATA_DIR_TO_HOST;
+//			reply = do_ADFU_acmbr(fsg);
+//			break;
+		case SC_ADFU_ACCESS_INTERNAL_RAM:
+			fsg->data_dir = DATA_DIR_FROM_HOST;
+			fsg->data_size_from_cmnd = get_le32(&fsg->cmnd[5]);
+			fsg->residue = fsg->usb_amount_left = fsg->data_size;
+			reply = do_ADFU_access_iram(fsg);
+			break;
+		case SC_ADFU_DOWNLOAD_IMG:
+//			printk("*******WRITE THE ROOTFS !!*******\n");
+			/* prepare */
+			/* fsg->data_size = */
+			fsg->data_dir = DATA_DIR_FROM_HOST;
+			fsg->data_size_from_cmnd = (get_le32(&fsg->cmnd[5]))<<9;
+			fsg->residue = fsg->usb_amount_left = fsg->data_size;
+			reply = do_ADFU_wtrootfs(fsg);
+//			printk("handle SC_ADFU_WRITE_ROOTFS end\n");
+			break;
+		case SC_ADFU_INFO:
+			fsg->data_dir = DATA_DIR_TO_HOST;
+			fsg->data_size_from_cmnd = get_le32(&fsg->cmnd[5]);
+			fsg->residue = fsg->usb_amount_left = fsg->data_size;
+			reply = do_ADFU_INFO(fsg);
+			break;
+//		case SC_ADFU_READ_ROOTFS:
+//		/* printk(KERN_INFO "*******READ THE ROOTFS !!*******\n"); */
+//			/* prepare */
+//			/* fsg->data_size = */
+//			fsg->data_dir = DATA_DIR_TO_HOST;
+//			fsg->data_size_from_cmnd = get_le32(&fsg->cmnd[9]);
+//			fsg->residue = fsg->usb_amount_left = fsg->data_size;
+//			reply = do_ADFU_rdrootfs(fsg);
+//			break;
+		case SC_ADFU_TFEROVER:
+			printk("SC_ADFU_TFEROVER\n");
+
+			//vfs_fsync(curlun->filp, 1);
+			sys_sync();     //sync all filesystem,avoid the error of checksum
+			mdelay(500);
+			sys_sync();
+			adfu_sync_bdev("/dev/acta");
+			adfu_sync_bdev("/dev/actb");
+			adfu_sync_bdev("/dev/actc");
+
+			adfu_sync_bdev("/dev/actd");
+			adfu_sync_bdev("/dev/acte");
+			adfu_sync_bdev("/dev/actf");
+			
+			adfu_sync_bdev("/dev/actg");
+			adfu_sync_bdev("/dev/acth");
+			adfu_sync_bdev("/dev/acti");
+//			curlun->filp->f_op->unlocked_ioctl(curlun->filp,BLKFLSBUF,0);   //write_back flash buffer
+
+			if (need_checksum) {
+				if (adfu_do_checksum(fsg)) {
+					printk("UPGRADE CHECKSUM ERROR.\n");
+					curlun->sense_data = SS_CHECKSUM_FAIL;
+				}
+				else {
+					printk("UPGRADE CHECKSUM OK.\n");	
+				}
+			}
+			
+			//update phy if downloading misc.img or updating mbr_info.bin
+			if((update_phy_boot == 1) || (check_partition_flag > 0))
+			{
+				set_probatch_phase(PROBATCH_WRITE_PHY);
+				wait_adfus_proc(PROBATCH_FINISH_WRITE_PHY);	
+			}
+	
+			//check udisk formatted ?					
+			set_probatch_phase(PROBATCH_FINISH);
+			wait_adfus_proc(PROBATCH_FINISH_OK);		
+
+			//vfs_fsync(curlun->filp, 1);
+			sys_sync();     //sync all filesystem
+			//adfu_sync_bdev("/dev/actk");
+//			curlun->filp->f_op->unlocked_ioctl(curlun->filp,BLKFLSBUF,0);   //write_back flash buffer
+			mdelay(1000);
+			break;
+		}
+		break;
+
+	case SC_ADFU_SUCCESSFUL:
+		fsg->curlun = curlun = &fsg->luns[0];
+		curlun->sense_data = SS_NO_SENSE;
+		curlun->sense_data_info = 0;
+		curlun->info_valid = 0;
+		adfu_success_flag = 1;
+		//vfs_fsync(curlun->filp, 1);
+//		curlun->filp->f_op->unlocked_ioctl(curlun->filp,BLKFLSBUF,0);   //write_back flash buffer
+
+		break;
+
+	/* Some mandatory commands that we recognize but don't implement.
+	 * They don't mean much in this setting.  It's left as an exercise
+	 * for anyone interested to implement RESERVE and RELEASE in terms
+	 * of Posix locks. */
+	case SC_FORMAT_UNIT:
+	case SC_RELEASE:
+	case SC_RESERVE:
+	case SC_SEND_DIAGNOSTIC:
+	/* printk(KERN_INFO "SC_ENTENSIVE.\n"); */
+
+	default:
+	/* printk(KERN_INFO "SC_UNKNOW.\n"); */
+
+		fsg->data_size_from_cmnd = 0;
+		sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
+		reply = check_command(fsg, fsg->cmnd_size,
+					DATA_DIR_UNKNOWN, 0xff, 0,
+					unknown);
+		if (reply == 0) {
+			fsg->curlun->sense_data = SS_INVALID_COMMAND;
+			reply = -EINVAL;
+		}
+		break;
+	}
+	up_read(&fsg->filesem);
+
+	if (reply == -EINTR || signal_pending(current)) {
+		/* */
+		return -EINTR;
+	}
+	/* Set up the single reply buffer for finish_reply() */
+	if (reply == -EINVAL)
+		reply = 0;	/* Error reply length */
+	if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
+		reply = min((u32) reply, fsg->data_size_from_cmnd);
+		bh->inreq->length = reply;
+		bh->state = BUF_STATE_FULL;
+		fsg->residue -= reply;
+	}			/* Otherwise it's already set */
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+{
+	struct usb_request *req = bh->outreq;
+	struct bulk_cb_wrap *cbw = req->buf;
+	/* Was this a real packet?  Should it be ignored? */
+	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+		return -EINVAL;
+#if 0
+	int k;
+	printk(KERN_INFO "CDB:");
+	for (k = 0; k < MAX_COMMAND_SIZE; k++) {
+		/**/
+		printk(KERN_INFO "%x ", cbw->CDB[k]);
+	}
+	printk(KERN_INFO "\n");
+	printk(KERN_INFO "Signature:%x Tag:%x Flags: \
+		%x DataTransferLength:%x\n",
+	       cbw->Signature, cbw->Tag, cbw->Flags,
+	       le32_to_cpu(cbw->DataTransferLength));
+#endif
+
+#if 0
+	/* Is the CBW valid? */
+	if (req->actual != USB_BULK_CB_WRAP_LEN ||
+	    cbw->Signature != __constant_cpu_to_le32(USB_BULK_CB_SIG)) {
+		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
+		    req->actual, le32_to_cpu(cbw->Signature));
+
+		/* The Bulk-only spec says we MUST stall the IN endpoint
+		 * (6.6.1), so it's unavoidable.  It also says we must
+		 * retain this state until the next reset, but there's
+		 * no way to tell the controller driver it should ignore
+		 * Clear-Feature(HALT) requests.
+		 *
+		 * We aren't required to halt the OUT endpoint; instead
+		 * we can simply accept and discard any data received
+		 * until the next reset. */
+		wedge_bulk_in_endpoint(fsg);
+		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+		return -EINVAL;
+	}
+
+	/* Is the CBW meaningful? */
+	if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
+	    cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
+		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
+		    "cmdlen %u\n", cbw->Lun, cbw->Flags, cbw->Length);
+
+		/* We can do anything we want here, so let's stall the
+		 * bulk pipes if we are allowed to. */
+		if (mod_data.can_stall) {
+			//fsg_set_halt(fsg, fsg->bulk_out);
+			halt_bulk_in_endpoint(fsg);
+		}
+		return -EINVAL;
+	}
+common_use:
+#endif	
+	/* Save the command for later */
+	fsg->cmnd_size = cbw->Length;
+	memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
+	if (cbw->Flags & USB_BULK_IN_FLAG)
+		fsg->data_dir = DATA_DIR_TO_HOST;
+	else
+		fsg->data_dir = DATA_DIR_FROM_HOST;
+	fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
+	if (fsg->data_size == 0)
+		fsg->data_dir = DATA_DIR_NONE;
+	fsg->lun = cbw->Lun;
+	fsg->tag = cbw->Tag;
+	return 0;
+}
+
+static int get_next_command(struct fsg_dev *fsg)
+{
+	struct fsg_buffhd *bh;
+	int rc = 0;
+	if (transport_is_bbb()) {
+
+		/* Wait for the next buffer to become available */
+		bh = fsg->next_buffhd_to_fill;
+		while (bh->state != BUF_STATE_EMPTY) {
+			rc = sleep_thread(fsg);
+			if (rc)
+				return rc;
+
+		}
+
+		/* Queue a request to read a Bulk-only CBW */
+		set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
+		bh->outreq->short_not_ok = 1;
+		/* printk(KERN_INFO
+		   "get command length: %d\n",bh->outreq->length); */
+		start_transfer(fsg, fsg->bulk_out, bh->outreq,
+			       &bh->outreq_busy, &bh->state);
+
+		/* We will drain the buffer in software, which means we
+		 * can reuse it for the next filling.  No need to advance
+		 * next_buffhd_to_fill. */
+
+		/* Wait for the CBW to arrive */
+		while (bh->state != BUF_STATE_FULL) {
+			rc = sleep_thread(fsg);
+			if (rc)
+				return rc;
+
+		}
+		smp_rmb();
+		rc = received_cbw(fsg, bh);
+		bh->state = BUF_STATE_EMPTY;
+
+	} else {		/* USB_PR_CB or USB_PR_CBI */
+
+		unsigned long flag;
+		/* Wait for the next command to arrive */
+		while (fsg->cbbuf_cmnd_size == 0) {
+			rc = sleep_thread(fsg);
+			if (rc)
+				return rc;
+		}
+
+		/* Is the previous status interrupt request still busy?
+		 * The host is allowed to skip reading the status,
+		 * so we must cancel it. */
+
+		if (fsg->intreq_busy)
+			usb_ep_dequeue(fsg->intr_in, fsg->intreq);
+
+		/* Copy the command and mark the buffer empty */
+		fsg->data_dir = DATA_DIR_UNKNOWN;
+		spin_lock_irqsave(&fsg->lock, flag);
+		fsg->cmnd_size = fsg->cbbuf_cmnd_size;
+		memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
+		fsg->cbbuf_cmnd_size = 0;
+		spin_unlock_irqrestore(&fsg->lock, flag);
+	}
+	return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
+			   const struct usb_endpoint_descriptor *d)
+{
+	int rc;
+
+	ep->driver_data = fsg;
+  ep->desc = d;
+	rc = usb_ep_enable(ep);
+	if (rc)
+		ERROR(fsg, "------can't enable %s, result %d\n", ep->name, rc);
+	return rc;
+}
+
+static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
+			 struct usb_request **preq)
+{
+	*preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
+	if (*preq)
+		return 0;
+	ERROR(fsg, "can't allocate request for %s\n", ep->name);
+	return -ENOMEM;
+}
+
+/*
+ * Reset interface setting and re-init endpoint state (toggle etc).
+ * Call with altsetting < 0 to disable the interface.  The only other
+ * available altsetting is 0, which enables the interface.
+ */
+static int do_set_interface(struct fsg_dev *fsg, int altsetting)
+{
+	int rc = 0;
+	int i;
+	const struct usb_endpoint_descriptor *d;
+
+	if (fsg->running)
+		DBG(fsg, "reset interface\n");
+
+reset:
+	/* Deallocate the requests */
+	for (i = 0; i < NUM_BUFFERS; ++i) {
+		struct fsg_buffhd *bh = &fsg->buffhds[i];
+
+		if (bh->inreq) {
+			usb_ep_free_request(fsg->bulk_in, bh->inreq);
+			bh->inreq = NULL;
+		}
+		if (bh->outreq) {
+			usb_ep_free_request(fsg->bulk_out, bh->outreq);
+			bh->outreq = NULL;
+		}
+	}
+	if (fsg->intreq) {
+		usb_ep_free_request(fsg->intr_in, fsg->intreq);
+		fsg->intreq = NULL;
+	}
+
+	/* Disable the endpoints */
+	if (fsg->bulk_in_enabled) {
+		usb_ep_disable(fsg->bulk_in);
+		fsg->bulk_in_enabled = 0;
+	}
+	if (fsg->bulk_out_enabled) {
+		usb_ep_disable(fsg->bulk_out);
+		fsg->bulk_out_enabled = 0;
+	}
+	if (fsg->intr_in_enabled) {
+		usb_ep_disable(fsg->intr_in);
+		fsg->intr_in_enabled = 0;
+	}
+
+	fsg->running = 0;
+	if (altsetting < 0 || rc != 0)
+		return rc;
+
+	DBG(fsg, "set interface %d\n", altsetting);
+
+	/* Enable the endpoints */
+	d = ep_desc(fsg->gadget, &fs_bulk_in_desc, &hs_bulk_in_desc);
+	rc = enable_endpoint(fsg, fsg->bulk_in, d);
+	if (rc != 0)
+		goto reset;
+	fsg->bulk_in_enabled = 1;
+
+	d = ep_desc(fsg->gadget, &fs_bulk_out_desc, &hs_bulk_out_desc);
+	rc = enable_endpoint(fsg, fsg->bulk_out, d);
+	if (rc != 0)
+		goto reset;
+	fsg->bulk_out_enabled = 1;
+	fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+
+	if (transport_is_cbi()) {
+		d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
+		rc = enable_endpoint(fsg, fsg->intr_in, d);
+		if (rc != 0)
+			goto reset;
+		fsg->intr_in_enabled = 1;
+	}
+
+	/* Allocate the requests */
+	for (i = 0; i < NUM_BUFFERS; ++i) {
+		struct fsg_buffhd *bh = &fsg->buffhds[i];
+		rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq);
+		if (rc != 0)
+			goto reset;
+		rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq);
+		if (rc != 0)
+			goto reset;
+		bh->inreq->buf = bh->outreq->buf = bh->buf;
+		bh->inreq->context = bh->outreq->context = bh;
+		bh->inreq->complete = bulk_in_complete;
+		bh->outreq->complete = bulk_out_complete;
+	}
+	if (transport_is_cbi()) {
+		rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq);
+		if (rc != 0)
+			goto reset;
+		fsg->intreq->complete = intr_in_complete;
+	}
+
+	fsg->running = 1;
+	for (i = 0; i < fsg->nluns; ++i)
+		fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
+	return rc;
+}
+
+/*
+ * Change our operational configuration.  This code must agree with the code
+ * that returns config descriptors, and with interface altsetting code.
+ *
+ * It's also responsible for power management interactions.  Some
+ * configurations might not work with our current power sources.
+ * For now we just assume the gadget is always self-powered.
+ */
+static int do_set_config(struct fsg_dev *fsg, u8 new_config)
+{
+	int rc = 0;
+
+	/* Disable the single interface */
+	if (fsg->config != 0) {
+		DBG(fsg, "reset config\n");
+		fsg->config = 0;
+		rc = do_set_interface(fsg, -1);
+	}
+
+	/* Enable the interface */
+	if (new_config != 0) {
+		fsg->config = new_config;
+		rc = do_set_interface(fsg, 0);
+		if (rc != 0)
+			fsg->config = 0;	/* Reset on errors */
+		else {
+			char *speed;
+
+			switch (fsg->gadget->speed) {
+			case USB_SPEED_LOW:
+				speed = "low";
+				break;
+			case USB_SPEED_FULL:
+				speed = "full";
+				break;
+			case USB_SPEED_HIGH:
+				speed = "high";
+				break;
+			default:
+				speed = "?";
+				break;
+			}
+			INFO(fsg, "%s speed config #%d\n", speed, fsg->config);
+		}
+	}
+	return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void handle_exception(struct fsg_dev *fsg)
+{
+	siginfo_t info;
+	int sig;
+	int i;
+	int num_active;
+	struct fsg_buffhd *bh;
+	enum fsg_state old_state;
+	u8 new_config;
+	struct lun *curlun;
+	unsigned int exception_req_tag;
+	unsigned long flag;
+	int rc;
+
+	/* Clear the existing signals.  Anything but SIGUSR1 is converted
+	 * into a high-priority EXIT exception. */
+	for (;;) {
+		sig = dequeue_signal_lock(current, &current->blocked, &info);
+		if (!sig)
+			break;
+		if (sig != SIGUSR1) {
+			if (fsg->state < FSG_STATE_EXIT)
+				DBG(fsg, "Main thread exiting on signal\n");
+			raise_exception(fsg, FSG_STATE_EXIT);
+		}
+	}
+
+	/* Cancel all the pending transfers */
+	if (fsg->intreq_busy)
+		usb_ep_dequeue(fsg->intr_in, fsg->intreq);
+	for (i = 0; i < NUM_BUFFERS; ++i) {
+		bh = &fsg->buffhds[i];
+		if (bh->inreq_busy) {
+			printk("bulk in dequeue\n");
+			usb_ep_dequeue(fsg->bulk_in, bh->inreq);
+		}
+		if (bh->outreq_busy) {
+			printk("bulk out dequeue\n");
+			usb_ep_dequeue(fsg->bulk_out, bh->outreq);
+		}
+	}
+
+	/* Wait until everything is idle */
+	for (;;) {
+		num_active = fsg->intreq_busy;
+		for (i = 0; i < NUM_BUFFERS; ++i) {
+			bh = &fsg->buffhds[i];
+			num_active += bh->inreq_busy + bh->outreq_busy;
+		}
+		if (num_active == 0)
+			break;
+		if (sleep_thread(fsg))
+			return;
+	}
+
+	/* Clear out the controller's fifos */
+	if (fsg->bulk_in_enabled)
+		usb_ep_fifo_flush(fsg->bulk_in);
+	if (fsg->bulk_out_enabled)
+		usb_ep_fifo_flush(fsg->bulk_out);
+	if (fsg->intr_in_enabled)
+		usb_ep_fifo_flush(fsg->intr_in);
+
+	/* Reset the I/O buffer states and pointers, the SCSI
+	 * state, and the exception.  Then invoke the handler. */
+	spin_lock_irqsave(&fsg->lock, flag);
+
+	for (i = 0; i < NUM_BUFFERS; ++i) {
+		bh = &fsg->buffhds[i];
+		bh->state = BUF_STATE_EMPTY;
+	}
+	fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain = &fsg->buffhds[0];
+
+	exception_req_tag = fsg->exception_req_tag;
+	new_config = fsg->new_config;
+	old_state = fsg->state;
+
+	if (old_state == FSG_STATE_ABORT_BULK_OUT)
+		fsg->state = FSG_STATE_STATUS_PHASE;
+	else {
+		for (i = 0; i < fsg->nluns; ++i) {
+			curlun = &fsg->luns[i];
+			curlun->prevent_medium_removal = 0;
+			curlun->sense_data = curlun->unit_attention_data =
+			    SS_NO_SENSE;
+			curlun->sense_data_info = 0;
+			curlun->info_valid = 0;
+		}
+		fsg->state = FSG_STATE_IDLE;
+	}
+	spin_unlock_irqrestore(&fsg->lock, flag);
+
+	/* Carry out any extra actions required for the exception */
+	switch (old_state) {
+	default:
+		break;
+
+	case FSG_STATE_ABORT_BULK_OUT:
+		send_status(fsg);
+		spin_lock_irqsave(&fsg->lock, flag);
+		if (fsg->state == FSG_STATE_STATUS_PHASE)
+			fsg->state = FSG_STATE_IDLE;
+		spin_unlock_irqrestore(&fsg->lock, flag);
+		break;
+	case FSG_STATE_RESET:
+		/* In case we were forced against our will to halt a
+		 * bulk endpoint, clear the halt now.  (The SuperH UDC
+		 * requires this.) */
+		if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+			usb_ep_clear_halt(fsg->bulk_in);
+
+		if (transport_is_bbb()) {
+			if (fsg->ep0_req_tag == exception_req_tag)
+				ep0_queue(fsg);	/* Complete the status stage */
+
+		} else if (transport_is_cbi())
+			send_status(fsg);	/* Status by interrupt pipe */
+
+		/* Technically this should go here, but it would only be
+		 * a waste of time.  Ditto for the INTERFACE_CHANGE and
+		 * CONFIG_CHANGE cases. */
+		/* for (i = 0; i < fsg->nluns; ++i)
+		   fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; */
+		break;
+	case FSG_STATE_INTERFACE_CHANGE:
+		rc = do_set_interface(fsg, 0);
+		if (fsg->ep0_req_tag != exception_req_tag)
+			break;
+		if (rc != 0) {	/* STALL on errors */
+			fsg_set_halt(fsg, fsg->ep0);
+		} else		/* Complete the status stage */
+			ep0_queue(fsg);
+		break;
+
+	case FSG_STATE_CONFIG_CHANGE:
+		rc = do_set_config(fsg, new_config);
+		if (fsg->ep0_req_tag != exception_req_tag)
+			break;
+		if (rc != 0) {	/* STALL on errors */
+			fsg_set_halt(fsg, fsg->ep0);
+		} else		/* Complete the status stage */
+			ep0_queue(fsg);
+		break;
+
+	case FSG_STATE_DISCONNECT:
+		fsync_all(fsg);
+		do_set_config(fsg, 0);	/* Unconfigured state */
+        if (unlikely(adfu_success_flag == 1)) {
+            usb_gadget_disconnect(fsg->gadget);
+            
+            if(need_restart == 1)   //shutdown
+            {
+                kernel_restart("upgrade_halt");
+            }
+            else if(need_restart == 2)  //reboot
+            {
+                kernel_restart("reboot");
+            }
+            else
+            {     
+                //do nothing           
+            }
+    	}
+		break;
+
+	case FSG_STATE_EXIT:
+	case FSG_STATE_TERMINATED:
+		do_set_config(fsg, 0);	/* Free resources */
+		spin_lock_irqsave(&fsg->lock, flag);
+		fsg->state = FSG_STATE_TERMINATED;	/* Stop the thread */
+		spin_unlock_irqrestore(&fsg->lock, flag);
+		break;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int fsg_main_thread(void *fsg_)
+{
+	struct fsg_dev *fsg = fsg_;
+	unsigned long flag;
+	/* Allow the thread to be killed by a signal, but set the signal mask
+	 * to block everything but INT, TERM, KILL, and USR1. */
+	allow_signal(SIGINT);
+	allow_signal(SIGTERM);
+	allow_signal(SIGKILL);
+	allow_signal(SIGUSR1);
+
+	/* Allow the thread to be frozen */
+	set_freezable();
+
+	/* Arrange for userspace references to be interpreted as kernel
+	 * pointers.  That way we can pass a kernel pointer to a routine
+	 * that expects a __user pointer and it will work okay. */
+	set_fs(get_ds());
+
+	/* The main loop */
+	while (fsg->state != FSG_STATE_TERMINATED) {
+
+		if (exception_in_progress(fsg) || signal_pending(current)) {
+			handle_exception(fsg);
+			continue;
+		}
+
+		if (!fsg->running) {
+			sleep_thread(fsg);
+			continue;
+		}
+
+		if (get_next_command(fsg))
+			continue;
+
+		spin_lock_irqsave(&fsg->lock, flag);
+		if (!exception_in_progress(fsg))
+			fsg->state = FSG_STATE_DATA_PHASE;
+		spin_unlock_irqrestore(&fsg->lock, flag);
+
+		if (do_scsi_command(fsg) || finish_reply(fsg))
+			continue;
+
+		spin_lock_irqsave(&fsg->lock, flag);
+		if (!exception_in_progress(fsg))
+			fsg->state = FSG_STATE_STATUS_PHASE;
+		spin_unlock_irqrestore(&fsg->lock, flag);
+
+		if (send_status(fsg))
+			continue;
+
+		spin_lock_irqsave(&fsg->lock, flag);
+		if (!exception_in_progress(fsg))
+			fsg->state = FSG_STATE_IDLE;
+		spin_unlock_irqrestore(&fsg->lock, flag);
+	}
+
+	spin_lock_irqsave(&fsg->lock, flag);
+	fsg->thread_task = NULL;
+	spin_unlock_irqrestore(&fsg->lock, flag);
+
+	/* In case we are exiting because of a signal, unregister the
+	 * gadget driver and close the backing file. */
+	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) {
+		usb_gadget_unregister_driver(&fsg_driver);
+		close_all_backing_files(fsg);
+	}
+
+	/* Let the unbind and cleanup routines know the thread has exited */
+	complete_and_exit(&fsg->thread_notifier, 0);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* If the next two routines are called while the gadget is registered,
+ * the caller must own fsg->filesem for writing. */
+#if 0
+static int open_backing_file(struct lun *curlun, const char *filename)
+{
+	int ro;
+	struct file *filp = NULL;
+	int rc = -EINVAL;
+	struct inode *inode = NULL;
+	loff_t size;
+	loff_t num_sectors;
+
+	/* R/W if we can, R/O if we must */
+	ro = curlun->ro;
+	if (!ro) {
+		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
+		if (-EROFS == PTR_ERR(filp))
+			ro = 1;
+	}
+	if (ro)
+		filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
+	if (IS_ERR(filp)) {
+		LINFO(curlun, "unable to open backing file: %s\n", filename);
+		return PTR_ERR(filp);
+	}
+
+	if (!(filp->f_mode & FMODE_WRITE))
+		ro = 1;
+
+	if (filp->f_path.dentry)
+		inode = filp->f_path.dentry->d_inode;
+	if (inode && S_ISBLK(inode->i_mode)) {
+		if (bdev_read_only(inode->i_bdev))
+			ro = 1;
+	} else if (!inode || !S_ISREG(inode->i_mode)) {
+		LINFO(curlun, "invalid file type: %s\n", filename);
+		goto out;
+	}
+
+	/* If we can't read the file, it's no good.
+	 * If we can't write the file, use it read-only. */
+	if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) {
+		LINFO(curlun, "file not readable: %s\n", filename);
+		goto out;
+	}
+	if (!(filp->f_op->write || filp->f_op->aio_write))
+		ro = 1;
+
+	size = i_size_read(inode->i_mapping->host);
+	if (size < 0) {
+		LINFO(curlun, "unable to find file size: %s\n", filename);
+		rc = (int)size;
+		goto out;
+	}
+	num_sectors = size >> 9;	/* File size in 512-byte sectors */
+	if (num_sectors == 0) {
+		LINFO(curlun, "file too small: %s\n", filename);
+		rc = -ETOOSMALL;
+		goto out;
+	}
+
+	get_file(filp);
+
+	curlun->devnum = filp->f_path.dentry->d_inode->i_rdev;
+	/* add by wlt, disk type decided */
+	if (MAJOR(filp->f_path.dentry->d_inode->i_rdev) == MAJOR_OF_CARD) {
+		printk("device num:MAJOR: %u MINOR: %u\n",
+				MAJOR(filp->f_path.dentry->d_inode->i_rdev),
+				MINOR(filp->f_path.dentry->d_inode->i_rdev));
+		curlun->disk_type = CARD_MEDIUM;
+		card_dirty_flag = 0;
+	}
+	else if (MAJOR(filp->f_path.dentry->d_inode->i_rdev) == MAJOR_OF_NAND) {
+		printk("device num:MAJOR: %u MINOR: %u\n",
+				MAJOR(filp->f_path.dentry->d_inode->i_rdev),
+				MINOR(filp->f_path.dentry->d_inode->i_rdev));
+		curlun->disk_type = NAND_MEDIUM;
+		nand_dirty_flag = 0;
+	}
+	else if (MAJOR(filp->f_path.dentry->d_inode->i_rdev) == MAJOR_OF_MMS) {
+		printk("device num:MAJOR: %u MINOR: %u\n",
+				MAJOR(filp->f_path.dentry->d_inode->i_rdev),
+				MINOR(filp->f_path.dentry->d_inode->i_rdev));
+		curlun->disk_type = MMS_MEDIUM;
+		card_dirty_flag = 0;
+	}
+	curlun->ro = ro;
+	curlun->filp = filp;
+	curlun->file_length = size;
+	curlun->num_sectors = num_sectors;
+	LDBG(curlun, "open backing file: %s\n", filename);
+	rc = 0;
+
+out:
+	filp_close(filp, current->files);
+	return rc;
+}
+#endif
+static void close_backing_file(struct lun *curlun)
+{
+	if (curlun->filp) {
+		LDBG(curlun, "close backing file\n");
+		fput(curlun->filp);
+		curlun->filp = NULL;
+	}
+}
+
+static void close_all_backing_files(struct fsg_dev *fsg)
+{
+	int i;
+
+	for (i = 0; i < fsg->nluns; ++i)
+		close_backing_file(&fsg->luns[i]);
+}
+
+static ssize_t show_ro(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct lun *curlun = dev_to_lun(dev);
+
+	return sprintf(buf, "%d\n", curlun->ro);
+}
+
+static ssize_t show_file(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct lun *curlun = dev_to_lun(dev);
+	struct fsg_dev *fsg = dev_get_drvdata(dev);
+	char *p;
+	ssize_t rc;
+
+	down_read(&fsg->filesem);
+	if (backing_file_is_open(curlun)) {	/* Get the complete pathname */
+		p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1);
+		if (IS_ERR(p))
+			rc = PTR_ERR(p);
+		else {
+			rc = strlen(p);
+			memmove(buf, p, rc);
+			buf[rc] = '\n';	/* Add a newline */
+			buf[++rc] = 0;
+		}
+	} else {		/* No file, return 0 bytes */
+		*buf = 0;
+		rc = 0;
+	}
+	up_read(&fsg->filesem);
+	return rc;
+}
+
+static ssize_t store_ro(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	ssize_t rc = count;
+	struct lun *curlun = dev_to_lun(dev);
+	struct fsg_dev *fsg = dev_get_drvdata(dev);
+	int i;
+
+	if (sscanf(buf, "%d", &i) != 1)
+		return -EINVAL;
+
+	/* Allow the write-enable status to change only while the backing file
+	 * is closed. */
+	down_read(&fsg->filesem);
+	if (backing_file_is_open(curlun)) {
+		LDBG(curlun, "read-only status change prevented\n");
+		rc = -EBUSY;
+	} else {
+		curlun->ro = !!i;
+		LDBG(curlun, "read-only status set to %d\n", curlun->ro);
+	}
+	up_read(&fsg->filesem);
+	return rc;
+}
+
+static ssize_t store_file(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	return count;
+#if 0
+	struct lun *curlun = dev_to_lun(dev);
+	struct fsg_dev *fsg = dev_get_drvdata(dev);
+	int rc = 0;
+#if 0
+	if (curlun->prevent_medium_removal
+			&& backing_file_is_open(curlun)) {
+		LDBG(curlun, "eject attempt prevented\n");
+		return -EBUSY;
+		/* "Door is locked" */
+	}
+#endif
+	/* Remove a trailing newline */
+	if (count > 0 && buf[count - 1] == '\n')
+		((char *)buf)[count - 1] = 0;
+	/* Ugh! */
+
+	/* Eject current medium */
+	down_write(&fsg->filesem);
+	if (backing_file_is_open(curlun)) {
+		close_backing_file(curlun);
+		curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
+	}
+
+	/* Load new medium */
+	if (count > 0 && buf[0]) {
+		rc = open_backing_file(curlun, buf);
+		if (rc == 0)
+			curlun->unit_attention_data =
+			    SS_NOT_READY_TO_READY_TRANSITION;
+	}
+	up_write(&fsg->filesem);
+	return rc < 0 ? rc : count;
+#endif
+}
+
+/* The write permissions and store_xxx pointers are set in fsg_bind() */
+static DEVICE_ATTR(ro, 0444, show_ro, NULL);
+static DEVICE_ATTR(file, 0444, show_file, NULL);
+
+
+static ssize_t show_need_format(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return sprintf(buf, "%d", need_format);
+}
+
+static ssize_t store_need_format(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	/* for future use */
+	return 0;
+}
+
+static DEVICE_ATTR(need_format, 0444, show_need_format, NULL);
+
+static ssize_t show_fs_name(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return sprintf(buf, "%s", format_fs_name);
+}
+
+static ssize_t show_disk_name(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return sprintf(buf, "%s", format_disk_name);
+}
+
+static ssize_t show_mbrc_name(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return sprintf(buf, "%s", mbrc_name);
+}
+
+static ssize_t show_disk_label(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return sprintf(buf, "%s", format_disk_label);
+}
+
+static DEVICE_ATTR(format_fs_name, 0444, show_fs_name, NULL);
+static DEVICE_ATTR(format_disk_name, 0444, show_disk_name, NULL);
+static DEVICE_ATTR(format_disk_label, 0444, show_disk_label, NULL);
+static DEVICE_ATTR(mbrc_name, 0444, show_mbrc_name, NULL);
+/*-------------------------------------------------------------------------*/
+
+static void fsg_release(struct kref *ref)
+{
+	struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref);
+
+	kfree(fsg->luns);
+	kfree(fsg);
+}
+
+static void lun_release(struct device *dev)
+{
+	struct fsg_dev *fsg = dev_get_drvdata(dev);
+
+	kref_put(&fsg->ref, fsg_release);
+}
+
+static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
+{
+	struct fsg_dev *fsg = get_gadget_data(gadget);
+	int i;
+	struct lun *curlun;
+	struct usb_request *req = fsg->ep0req;
+
+	DBG(fsg, "unbind\n");
+	clear_bit(REGISTERED, &fsg->atomic_bitflags);
+
+	/* Unregister the sysfs attribute files and the LUNs */
+	for (i = 0; i < fsg->nluns; ++i) {
+		curlun = &fsg->luns[i];
+		if (curlun->registered) {
+			device_remove_file(&curlun->dev, &dev_attr_ro);
+			device_remove_file(&curlun->dev, &dev_attr_file);
+			device_unregister(&curlun->dev);
+			curlun->registered = 0;
+		}
+	}
+
+	/* If the thread isn't already dead, tell it to exit now */
+	if (fsg->state != FSG_STATE_TERMINATED) {
+		raise_exception(fsg, FSG_STATE_EXIT);
+		wait_for_completion(&fsg->thread_notifier);
+
+		/* The cleanup routine waits for this completion also */
+		complete(&fsg->thread_notifier);
+	}
+
+	/* Free the data buffers */
+	for (i = 0; i < NUM_BUFFERS; ++i) {
+		/* kfree(fsg->buffhds[i].buf); */
+		struct fsg_buffhd *bh = &fsg->buffhds[i];
+		if (bh->buf)
+			kfree(bh->buf);
+	}
+	/* Free the request and buffer for endpoint 0 */
+	if (req) {
+		kfree(req->buf);
+		usb_ep_free_request(fsg->ep0, req);
+	}
+
+	set_gadget_data(gadget, NULL);
+}
+
+static int __init check_parameters(struct fsg_dev *fsg)
+{
+	int prot;
+	int gcnum;
+
+	/* Store the default values */
+	mod_data.transport_type = USB_PR_BULK;
+	mod_data.transport_name = "Bulk-only";
+	mod_data.protocol_type = USB_SC_8070;
+	mod_data.protocol_name = "8070i";
+
+	if (gadget_is_at91(fsg->gadget))
+		mod_data.can_stall = 0;
+
+	if (mod_data.release == 0xffff) {	/* Parameter wasn't set */
+		gcnum = get_default_bcdDevice(); //usb_gadget_controller_number(fsg->gadget);
+		if (gcnum >= 0)
+			mod_data.release = 0x0300 + gcnum;
+		else {
+			WARNING(fsg, "controller '%s' not recognized\n",
+				fsg->gadget->name);
+			mod_data.release = 0x0399;
+		}
+	}
+
+	prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
+	return 0;
+}
+
+/* just for test */
+#if 0
+static int do_ADFU_acmbr(struct fsg_dev *fsg)
+{
+	struct lun *curlun = fsg->curlun;
+	u32 lba;
+	struct fsg_buffhd *bh;
+	int rc;
+	u32 amount_left;
+	loff_t file_offset, file_offset_tmp;
+	unsigned int amount;
+	unsigned int partial_page;
+	ssize_t nread;
+
+	/* Get the starting Logical Block Address and check that it's
+	 * not too big */
+	lba = 0;
+	file_offset = ((loff_t) lba) << 9;
+
+	/* Carry out the file reads */
+	amount_left = fsg->data_size_from_cmnd = 0x400;
+	if (unlikely(amount_left == 0))
+		return -EIO;	/* No default reply */
+
+	for (;;) {
+
+		/* Figure out how much we need to read:
+		 * Try to read the remaining amount.
+		 * But don't read more than the buffer size.
+		 * And don't try to read past the end of the file.
+		 * Finally, if we're not at a page boundary, don't read past
+		 *      the next page.
+		 * If this means reading 0 then we were asked to read past
+		 *      the end of file. */
+		amount = min((unsigned int)amount_left, mod_data.buflen);
+		amount = min((loff_t) amount,
+			     curlun->file_length - file_offset);
+		partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
+		if (partial_page > 0)
+			amount = min(amount, (unsigned int)PAGE_CACHE_SIZE -
+				     partial_page);
+
+		/* Wait for the next buffer to become available */
+		bh = fsg->next_buffhd_to_fill;
+		while (bh->state != BUF_STATE_EMPTY) {
+			rc = sleep_thread(fsg);
+			if (rc)
+				return rc;
+		}
+
+		/* If we were asked to read past the end of file,
+		 * end with an empty buffer. */
+		if (amount == 0) {
+			curlun->sense_data =
+			    SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
+			curlun->sense_data_info = file_offset >> 9;
+			curlun->info_valid = 1;
+			bh->inreq->length = 0;
+			bh->state = BUF_STATE_FULL;
+			break;
+		}
+
+		/* Perform the read */
+		file_offset_tmp = file_offset;
+		nread = vfs_read(curlun->filp,
+				 (char __user *)bh->buf,
+				 amount, &file_offset_tmp);
+		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
+		      (unsigned long long)file_offset, (int)nread);
+		if (signal_pending(current))
+			return -EINTR;
+
+		if (nread < 0) {
+			LDBG(curlun, "error in file read: %d\n", (int)nread);
+			nread = 0;
+		} else if (nread < amount) {
+			LDBG(curlun, "partial file read: %d/%u\n",
+			     (int)nread, amount);
+			nread -= (nread & 511);	/* Round down to a block */
+		}
+		file_offset += nread;
+		amount_left -= nread;
+		fsg->residue -= nread;
+		bh->inreq->length = nread;
+		bh->state = BUF_STATE_FULL;
+
+		/* If an error occurred, report it and its position */
+		if (nread < amount) {
+			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
+			curlun->sense_data_info = file_offset >> 9;
+			curlun->info_valid = 1;
+			break;
+		}
+
+		if (amount_left == 0)
+			break;	/* No more left to read */
+
+		/* Send this buffer and go read some more */
+		bh->inreq->zero = 0;
+		start_transfer(fsg, fsg->bulk_in, bh->inreq,
+			       &bh->inreq_busy, &bh->state);
+		fsg->next_buffhd_to_fill = bh->next;
+	}
+
+	return -EIO;		/* No default reply */
+}
+#endif
+
+static int fsg_bind(struct usb_gadget *gadget, struct usb_gadget_driver *driver)
+{
+	struct fsg_dev *fsg = the_fsg;
+	int rc;
+	int i;
+	struct lun *curlun;
+	struct usb_ep *ep;
+	struct usb_request *req;
+	char *pathbuf, *p;
+
+	fsg->gadget = gadget;
+	set_gadget_data(gadget, fsg);
+	fsg->ep0 = gadget->ep0;
+	fsg->ep0->driver_data = fsg;
+	rc = check_parameters(fsg);
+	if (rc != 0)
+		goto out;
+
+	if (mod_data.removable) {	/* Enable the store_xxx attributes */
+		dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644;
+		dev_attr_ro.store = store_ro;
+		dev_attr_file.store = store_file;
+	}
+
+	dev_attr_need_format.store = store_need_format;
+
+	/* Find out how many LUNs there should be */
+	i = mod_data.nluns;
+	if (i == 0)
+		i = max(mod_data.num_filenames, 1u);
+	if (i > MAX_LUNS) {
+		ERROR(fsg, "invalid number of LUNs: %d\n", i);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* Create the LUNs, open their backing files, and register the
+	 * LUN devices in sysfs. */
+	fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL);
+	if (!fsg->luns) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	fsg->nluns = i;
+
+	mod_data.file[0] = "/dev/actb";
+	mod_data.file[1] = "/dev/acta";
+
+	for (i = 0; i < fsg->nluns; ++i) {
+		curlun = &fsg->luns[i];
+		curlun->ro = mod_data.ro[i];
+		curlun->dev.release = lun_release;
+		curlun->dev.parent = &gadget->dev;
+		curlun->dev.driver = &fsg_driver.driver;
+		dev_set_drvdata(&curlun->dev, fsg);
+		dev_set_name(&curlun->dev, "%s-lun%d",
+			     dev_name(&gadget->dev), i);
+		rc = device_register(&curlun->dev);
+		if (rc != 0) {
+			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
+			goto out;
+		}
+		if ((rc = device_create_file(&curlun->dev, &dev_attr_ro)) != 0 ||
+		    (rc = device_create_file(&curlun->dev, &dev_attr_file)) != 0) {
+			device_unregister(&curlun->dev);
+			goto out;
+		}
+
+		/* when used for adfu, we should create a sysfile to support format nand */
+		rc = device_create_file(&curlun->dev, &dev_attr_need_format);
+		rc = device_create_file(&curlun->dev, &dev_attr_format_fs_name);
+		rc = device_create_file(&curlun->dev, &dev_attr_format_disk_name);
+		rc = device_create_file(&curlun->dev, &dev_attr_format_disk_label);
+		
+		rc = device_create_file(&curlun->dev, &dev_attr_mbrc_name);
+
+		curlun->registered = 1;
+		kref_get(&fsg->ref);
+#if 0
+		if (mod_data.file[i] && *mod_data.file[i]) {
+			rc = open_backing_file(curlun, mod_data.file[i]);
+			if (rc != 0)
+				goto out;
+		} else if (!mod_data.removable) {
+			ERROR(fsg, "no file given for LUN%d\n", i);
+			rc = -EINVAL;
+			goto out;
+		}
+#endif
+	}
+
+	/* Find all the endpoints we will use */
+	usb_ep_autoconfig_reset(gadget);
+	ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc);
+	if (!ep)
+		goto autoconf_fail;
+	ep->driver_data = fsg;	/* claim the endpoint */
+	fsg->bulk_in = ep;
+
+	ep = usb_ep_autoconfig(gadget, &fs_bulk_out_desc);
+	if (!ep)
+		goto autoconf_fail;
+	ep->driver_data = fsg;	/* claim the endpoint */
+	fsg->bulk_out = ep;
+
+	if (transport_is_cbi()) {
+		ep = usb_ep_autoconfig(gadget, &fs_intr_in_desc);
+		if (!ep)
+			goto autoconf_fail;
+		ep->driver_data = fsg;	/* claim the endpoint */
+		fsg->intr_in = ep;
+	}
+
+	/* Fix up the descriptors */
+	device_desc.idVendor = cpu_to_le16(mod_data.vendor);
+	device_desc.idProduct = cpu_to_le16(mod_data.product);
+	device_desc.bcdDevice = cpu_to_le16(mod_data.release);
+
+	i = (transport_is_cbi() ? 3 : 2);	/* Number of endpoints */
+	intf_desc.bNumEndpoints = i;
+	intf_desc.bInterfaceSubClass = mod_data.protocol_type;
+	intf_desc.bInterfaceProtocol = mod_data.transport_type;
+	fs_function[i + FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
+	if (act_gadget_is_dualspeed(gadget)) {
+		hs_function[i + HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
+
+		/* Assume endpoint addresses are the same for both speeds */
+		hs_bulk_in_desc.bEndpointAddress =
+		    fs_bulk_in_desc.bEndpointAddress;
+		hs_bulk_out_desc.bEndpointAddress =
+		    fs_bulk_out_desc.bEndpointAddress;
+		hs_intr_in_desc.bEndpointAddress =
+		    fs_intr_in_desc.bEndpointAddress;
+	}
+
+	if (gadget_is_otg(gadget))
+		otg_desc.bmAttributes |= USB_OTG_HNP;
+
+	rc = -ENOMEM;
+
+	/* Allocate the request and buffer for endpoint 0 */
+	fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
+	if (!req)
+		goto out;
+	req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
+	if (!req->buf)
+		goto out;
+	req->complete = ep0_complete;
+
+	/* Allocate the data buffers */
+	for (i = 0; i < NUM_BUFFERS; ++i) {
+		struct fsg_buffhd *bh = &fsg->buffhds[i];
+
+		/* Allocate for the bulk-in endpoint.  We assume that
+		 * the buffer will also work with the bulk-out (and
+		 * interrupt-in) endpoint. */
+		bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
+		if (!bh->buf)
+			goto out;
+		bh->next = bh + 1;
+	}
+	fsg->buffhds[NUM_BUFFERS - 1].next = &fsg->buffhds[0];
+
+	/* This should reflect the actual gadget power source */
+	usb_gadget_set_selfpowered(gadget);
+
+	snprintf(manufacturer, sizeof manufacturer, "Actions Disk");
+#if 0
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+		 init_utsname()->sysname, init_utsname()->release,
+		 gadget->name);
+#endif
+	/* On a real device, serial[] would be loaded from permanent
+	 * storage.  We just encode it from the driver version string. */
+	if (uniSerial == 0)
+	{
+		for (i = 0; i < sizeof(serial) - 2; i += 2) {
+			sprintf(&serial[i], "%02X", '0');
+		}
+		serial[0] = 0x2C;	//invalid serial
+	}
+	/* printk("Now The Serial is %s\n", serial); */
+	fsg->thread_task = kthread_create(fsg_main_thread, fsg,
+					  "file-storage-gadget");
+	if (IS_ERR(fsg->thread_task)) {
+		rc = PTR_ERR(fsg->thread_task);
+		goto out;
+	}
+#if 0
+	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
+	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
+#endif
+	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+	for (i = 0; i < fsg->nluns; ++i) {
+		curlun = &fsg->luns[i];
+		if (backing_file_is_open(curlun)) {
+			p = NULL;
+			if (pathbuf) {
+				p = d_path(&curlun->filp->f_path,
+					   pathbuf, PATH_MAX);
+				if (IS_ERR(p))
+					p = NULL;
+			}
+			LINFO(curlun, "ro=%d, file: %s\n",
+			      curlun->ro, (p ? p : "(error)"));
+		}
+	}
+	kfree(pathbuf);
+
+	DBG(fsg, "transport=%s (x%02x)\n",
+	    mod_data.transport_name, mod_data.transport_type);
+	DBG(fsg, "protocol=%s (x%02x)\n",
+	    mod_data.protocol_name, mod_data.protocol_type);
+	DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
+	    mod_data.vendor, mod_data.product, mod_data.release);
+	DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
+	    mod_data.removable, mod_data.can_stall, mod_data.buflen);
+	DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
+
+	set_bit(REGISTERED, &fsg->atomic_bitflags);
+
+	/* Tell the thread to start working */
+	wake_up_process(fsg->thread_task);
+
+	return 0;
+
+autoconf_fail:
+	ERROR(fsg, "unable to autoconfigure all endpoints\n");
+	rc = -ENOTSUPP;
+
+out:
+	fsg->state = FSG_STATE_TERMINATED;	/* The thread is dead */
+	fsg_unbind(gadget);
+	close_all_backing_files(fsg);
+	return rc;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void fsg_suspend(struct usb_gadget *gadget)
+{
+	struct fsg_dev *fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "suspend\n");
+	set_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+static void fsg_resume(struct usb_gadget *gadget)
+{
+	struct fsg_dev *fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "resume\n");
+	clear_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_gadget_driver fsg_driver = {
+	.max_speed = USB_SPEED_HIGH,
+	.function = (char *)longname,
+       .bind = fsg_bind,
+	.unbind = fsg_unbind,
+	.disconnect = fsg_disconnect,
+	.setup = fsg_setup,
+	.suspend = fsg_suspend,
+	.resume = fsg_resume,
+
+	.driver = {
+		   .name = (char *)shortname,
+		   .owner = THIS_MODULE,
+		   /* .release = ... */
+		   /* .suspend = ... */
+		   /* .resume = ...  */
+		   },
+};
+
+static int __init fsg_alloc(void)
+{
+	struct fsg_dev *fsg;
+
+	fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
+	if (!fsg)
+		return -ENOMEM;
+	spin_lock_init(&fsg->lock);
+	init_rwsem(&fsg->filesem);
+	kref_init(&fsg->ref);
+	init_completion(&fsg->thread_notifier);
+
+	the_fsg = fsg;
+	return 0;
+}
+
+extern int owl_get_boot_mode(void);
+int __init fsg_init(void)
+{
+	int rc;
+	struct fsg_dev *fsg;
+        
+
+	if(owl_get_boot_mode() != OWL_BOOT_MODE_UPGRADE)
+        	return -EACCES;
+	adfu_success_flag = 0;
+
+	no_finish_reply = 0;
+
+	rc = fsg_alloc();
+	if (rc != 0)
+		return rc;
+	fsg = the_fsg;
+	rc = usb_gadget_probe_driver(&fsg_driver);
+	if (rc != 0)
+		kref_put(&fsg->ref, fsg_release);
+	usb_gadget_connect(fsg->gadget);
+	return rc;
+}
+module_init(fsg_init);
+
+void __exit fsg_cleanup(void)
+{
+	struct fsg_dev *fsg = the_fsg;
+	printk("file-storage unload ... \n");
+	/* Unregister the driver iff the thread hasn't already done so */
+	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
+		usb_gadget_unregister_driver(&fsg_driver);
+
+	/* Wait for the thread to finish up */
+	wait_for_completion(&fsg->thread_notifier);
+
+	close_all_backing_files(fsg);
+	kref_put(&fsg->ref, fsg_release);
+}
+module_exit(fsg_cleanup);
diff --git a/drivers/usb/gadget/legacy/adfuserver.h b/drivers/usb/gadget/legacy/adfuserver.h
new file mode 100644
index 0000000..cac29bb
--- /dev/null
+++ b/drivers/usb/gadget/legacy/adfuserver.h
@@ -0,0 +1,85 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Actions Semi Inc.
+*/
+/******************************************************************************/
+
+/******************************************************************************/
+#ifndef __MBR_INFO_H__
+#define __MBR_INFO_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_PARTITION   	12
+#define HDCP_KEY_SIZE		308 	//bytes
+#define SERIAL_NO_SIZE		16   	//bytes
+#define PARTITION_TBL_SIZE	(MAX_PARTITION * sizeof(partition_info_t))
+
+
+#define RECOVERY_ACCESS      0
+#define MISC_ACCESS       1
+#define ROOTFS_ACCESS       2
+#define ANDROID_DATA_ACCESS 3
+#define ANDROID_CACHE_ACCESS 4
+
+#define SNAPSHOT_ACCESS		5
+#define WHD_ACCESS			6
+
+#define CONFIG_RW_ACCESS 	7
+
+
+#define UDISK_ACCESS        10
+
+typedef struct
+{
+    unsigned char   flash_ptn;                  //flash partition number
+    unsigned char   partition_num;              //ÿ\B8\F6\B7\D6\C7\F8\B6\D4Ӧ\C6\E4\CB\F9\D4ڵ\C4flash partition\B5ı\E0\BA\C5
+    unsigned short  reserved;                   //reserved\A3\BA\BD\AB\CD\D8չ\B3ɸ÷\D6\C7\F8\B5\C4\CA\F4\D0\D4
+    unsigned int    partition_cap;              //\B6\D4Ӧ\B7\D6\C7\F8\B5Ĵ\F3С
+}__attribute__ ((packed)) partition_info_t;
+
+
+typedef struct
+{
+    unsigned char   flash_ptn;                  //flash partition number
+    unsigned char   partition_num;              //ÿ\B8\F6\B7\D6\C7\F8\B6\D4Ӧ\C6\E4\CB\F9\D4ڵ\C4flash partition\B5ı\E0\BA\C5
+    unsigned short  phy_info;                   //reserved\A3\BA\BD\AB\CD\D8չ\B3ɸ÷\D6\C7\F8\B5\C4\CA\F4\D0\D4
+    unsigned int    partition_cap;              //\B6\D4Ӧ\B7\D6\C7\F8\B5Ĵ\F3С
+}__attribute__ ((packed)) CapInfo_t;
+
+
+/*
+ * don't re-order
+ */
+typedef struct
+{
+    partition_info_t partition_info[MAX_PARTITION];            //\B7\D6\C7\F8\D0\C5Ϣ\B1\ED
+    unsigned char HdcpKey[HDCP_KEY_SIZE];
+    unsigned char SerialNo[SERIAL_NO_SIZE];
+    unsigned char reserved[0x400 - PARTITION_TBL_SIZE - HDCP_KEY_SIZE - SERIAL_NO_SIZE];     //mbr_info_t\A3\AC\B4\F3СΪ1k\A3\ACΪ\D2Ժ\F3\C0\A9չ
+}__attribute__ ((packed)) mbr_info_t;
+
+
+
+/********************************************************************
+\B7\D6\C7\F8\B7\BDʽ\A3\ACԭ\D4\F2\C9Ϸ\D6\C7\F8\B0\B4˳\D0\F2\C5\C5\C1У\BA
+            flash_ptn       partition_num       partition_cap\B5ĵ\A5λ
+mbrc:           0                   0               block
+vmlinux         0                   1               M
+rootfs          1                   0               M
+configfs        1                   1               M
+others          2                   0~n             M
+
+\D2\D4partition_numΪ0xff\B1\ED\C3\F7\D7\EE\BA\F3һ\B8\F6\B7\D6\C7\F8
+*********************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
old mode 100644
new mode 100755
index 73a4dfb..f2c5d8d
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -14,9 +14,54 @@
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/nls.h>
+#include <linux/fs.h>
+#include <linux/of.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <asm/uaccess.h>
+
+#define UNIFIED_ASCII_SERIALNUM         0     //
+#define UNIFIED_UNICODE_SERIALNUM       1     //?\A1\ECa3?\A1\EC???unicode??
+#define NOUNIFIED_UNICODE_SERIALNUM    2     //??\A8\A8??\A1\ECa3?\A1\EC???unicode??
+#define NOUNIFIED_ASCII_SERIALNUM      3     //
+#define USB3_UMON_FDT_COMPATIBLE_ATM7039C  "actions,atm7039c-usb"
+#define USB3_UMON_FDT_COMPATIBLE_ATM7059A  "actions,atm7059tc-usb"
+#define DEFAULT_SERIAL_NO  "0123456789ABCDEF"
+
+char usbserialnumber[33];
+int HAVE_SERIALNUM = 1;
+
+//extern int get_config(const char *key, char *buff, int len);
+
+int usbgadget_get_serialnumber(void)
+{
+	struct file *filp = NULL;
+	mm_segment_t old_fs;
+	loff_t file_offset =0;
+	int	length;
+
+	/*get usb serialnumber from */
+	filp = filp_open("/data/usb_serialnumber", O_RDONLY, 0);
+	if(IS_ERR(filp)) {
+		printk("open usb_serialnumber ERR\n");
+		HAVE_SERIALNUM =0;
+		return PTR_ERR(filp);
+	}
+
+	HAVE_SERIALNUM =1;
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	length = vfs_read(filp, usbserialnumber, 32, &file_offset);
+	set_fs(old_fs);
+
+	filp_close(filp, NULL);
+
+	usbserialnumber[32] = '\0';
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usbgadget_get_serialnumber);
 
 
 /**
@@ -40,7 +85,10 @@ int
 usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
 {
 	struct usb_string	*s;
-	int			len;
+	int	len, value;
+	char key[33];
+	struct device_node *fdt_node;
+	const __be32 *property;
 
 	/* descriptor 0 has the language id */
 	if (id == 0) {
@@ -59,12 +107,62 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
 		return -EINVAL;
 
 	/* string descriptors have length, tag, then UTF16-LE text */
-	len = min ((size_t) 126, strlen (s->s));
-	len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN,
-			(wchar_t *) &buf[2], 126);
-	if (len < 0)
-		return -EINVAL;
-	buf [0] = (len + 1) * 2;
+	if(id == 4) {	  
+		fdt_node = of_find_compatible_node(NULL, NULL, USB3_UMON_FDT_COMPATIBLE_ATM7039C);
+		if (NULL == fdt_node) {
+			fdt_node = of_find_compatible_node(NULL, NULL, USB3_UMON_FDT_COMPATIBLE_ATM7059A);
+			if (NULL == fdt_node) {
+				printk("<usbstring>err: no usb3-fdt-compatible\n");
+				return -EINVAL;
+			}
+		}		
+		property = of_get_property(fdt_node, "usb_serialnumber_config", NULL);
+		value = be32_to_cpup(property);
+
+		if(!HAVE_SERIALNUM){    	
+	  		printk("there is no serialnum file store. use UNIFIED_UNICODE_SN forcely\n");
+			value = UNIFIED_UNICODE_SERIALNUM;
+		}
+		printk("usb serialnumber config is %d\n", value);
+		switch(value) {      
+			case UNIFIED_UNICODE_SERIALNUM:
+				len = min ((size_t) 126, strlen (DEFAULT_SERIAL_NO));
+				len = utf8s_to_utf16s(DEFAULT_SERIAL_NO, len, UTF16_LITTLE_ENDIAN,
+				(wchar_t *) &buf[2], 126);
+				if (len < 0)
+				    return -EINVAL;
+				buf [0] = (len + 1) * 2;
+				break;
+		    
+			case NOUNIFIED_UNICODE_SERIALNUM:
+				len = sizeof(usbserialnumber) / 2;
+				memcpy(key, usbserialnumber, len);
+				key[len] = '\0';
+				len = utf8s_to_utf16s(usbserialnumber, len, UTF16_LITTLE_ENDIAN,
+				(wchar_t *) &buf[2], 126);
+				if (len < 0)
+					return -EINVAL;
+				buf [0] = (len + 1) * 2;
+				break;
+			case NOUNIFIED_ASCII_SERIALNUM:
+			case UNIFIED_ASCII_SERIALNUM:
+			default:
+				len = min ((size_t) 126, strlen (DEFAULT_SERIAL_NO));
+				strncpy(&buf[2], DEFAULT_SERIAL_NO, len);
+				for(; len < 32; len++)
+					buf[len] = 0x2e;
+				buf [0] = 32;
+				break;        
+
+		}
+	}else {
+		len = min ((size_t) 126, strlen (s->s));
+		len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN, (wchar_t *) &buf[2], 126);
+		if (len < 0)
+			return -EINVAL;
+		buf [0] = (len + 1) * 2;
+	}
+  
 	buf [1] = USB_DT_STRING;
 	return buf [0];
 }
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
old mode 100644
new mode 100755
index 197a6a3..f2ad838
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -188,6 +188,13 @@ config USB_EHCI_HCD_STI
 	  Enable support for the on-chip EHCI controller found on
 	  STMicroelectronics consumer electronics SoC's.
 
+config USB_EHCI_HCD_SYNOPSYS
+       tristate "Support for Synopsys Host-AHB USB 2.0 controller"
+	depends on USB_EHCI_HCD
+	---help---
+	  Enable support for onchip USB controllers based on DesignWare USB 2.0
+	  Host-AHB Controller IP from Synopsys.
+
 config USB_EHCI_HCD_AT91
         tristate  "Support for Atmel on-chip EHCI USB controller"
         depends on USB_EHCI_HCD && ARCH_AT91
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
old mode 100644
new mode 100755
index da03d8b..6d69301
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -14,7 +14,7 @@ xhci-hcd-y := xhci.o xhci-mem.o
 xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
 xhci-hcd-y += xhci-trace.o
 
-xhci-plat-hcd-y := xhci-plat.o
+xhci-plat-hcd-y := xhci-plat.o uhost_hotplug_handle.o
 ifneq ($(CONFIG_USB_XHCI_MVEBU), )
 	xhci-plat-hcd-y		+= xhci-mvebu.o
 endif
@@ -33,6 +33,7 @@ obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o
 obj-$(CONFIG_USB_EHCI_HCD_OMAP)	+= ehci-omap.o
 obj-$(CONFIG_USB_EHCI_HCD_ORION)	+= ehci-orion.o
 obj-$(CONFIG_USB_EHCI_HCD_SPEAR)	+= ehci-spear.o
+obj-$(CONFIG_USB_EHCI_HCD_SYNOPSYS)	+= ehci-h20ahb.o
 obj-$(CONFIG_USB_EHCI_HCD_STI)	+= ehci-st.o
 obj-$(CONFIG_USB_EHCI_EXYNOS)	+= ehci-exynos.o
 obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
@@ -74,3 +75,5 @@ obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
 obj-$(CONFIG_USB_FUSBH200_HCD)	+= fusbh200-hcd.o
 obj-$(CONFIG_USB_FOTG210_HCD)	+= fotg210-hcd.o
 obj-$(CONFIG_USB_MAX3421_HCD)	+= max3421-hcd.o
+obj-$(CONFIG_USB_AOTG_HCD)	+= acts_hub.o
+acts_hub-y := aotg_debug.o aotg_ring.o aotg_hcd.o aotg_mon.o
diff --git a/drivers/usb/host/aotg_debug.c b/drivers/usb/host/aotg_debug.c
new file mode 100644
index 0000000..1bddc82
--- /dev/null
+++ b/drivers/usb/host/aotg_debug.c
@@ -0,0 +1,985 @@
+/*
+ * (C) Copyright www.actions-semi.com 2012-2014
+ *     Written by houjingkun. <houjingkun at actions-semi.com>
+ * 
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/hcd.h>
+#include <linux/timer.h>
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/../../fs/proc/internal.h>
+
+#include <mach/hardware.h>
+#include <linux/gpio.h>
+
+#include "aotg_hcd.h"
+#include "aotg_regs.h"
+#include "aotg_plat_data.h"
+//#include "aotg_dma.h"
+#include "aotg_debug.h"
+
+
+char aotg_hcd_proc_sign = 'n';
+unsigned int aotg_trace_onff = 0;
+
+void aotg_dbg_proc_output_ep(void)
+{
+	return;
+}
+
+void aotg_dbg_put_info(char *info0, unsigned int info1, unsigned int info2, unsigned int info3)
+{
+	return;
+}
+
+void aotg_dbg_output_info(void)
+{
+	return;
+}
+
+void aotg_dbg_put_q(struct aotg_queue *q, unsigned int num, unsigned int type, unsigned int len)
+{
+	return;
+}
+
+void aotg_dbg_finish_q(struct aotg_queue *q)
+{
+	return;
+}
+
+void aotg_dump_ep_reg(struct aotg_hcd *acthcd, int ep_index, int is_out)
+{
+	int index_multi = ep_index - 1;
+	if (NULL == acthcd) {
+		ACT_HCD_ERR
+		return;
+	}
+
+	if (ep_index > 15) {
+		printk("ep_index : %d too big, err!\n", ep_index);
+		return;
+	}	
+	
+	printk("=== dump hc-%s ep%d reg info ===\n",
+		is_out ? "out" : "in", ep_index);
+
+	if (ep_index == 0) {
+		printk(" HCIN0BC(0x%p) : 0x%X\n",
+	            acthcd->base + HCIN0BC, usb_readb(acthcd->base + HCIN0BC));
+		printk(" EP0CS(0x%p) : 0x%X\n",
+	            acthcd->base + EP0CS, usb_readb(acthcd->base + EP0CS));
+		printk(" HCOUT0BC(0x%p) : 0x%X\n",
+	            acthcd->base + HCOUT0BC, usb_readb(acthcd->base + HCOUT0BC));
+		printk(" HCEP0CTRL(0x%p) : 0x%X\n",
+	            acthcd->base + HCEP0CTRL, usb_readb(acthcd->base + HCEP0CTRL));
+		printk(" HCIN0ERR(0x%p) : 0x%X\n",
+				acthcd->base + HCIN0ERR, usb_readb(acthcd->base + HCIN0ERR));
+		return;
+	}
+	
+	if (is_out) {
+		printk(" HCOUT%dBC(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1BC + index_multi * 0x8,
+			usb_readw(acthcd->base + HCOUT1BC+ index_multi *0x8));	
+		printk(" HCOUT%dCON(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1CON + index_multi * 0x8,
+			usb_readb(acthcd->base + HCOUT1CON + index_multi *0x8));
+		printk(" HCOUT%dCS(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1CS + index_multi * 0x8,
+			usb_readb(acthcd->base + HCOUT1CS + index_multi *0x8));
+		printk(" HCOUT%dCTRL(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1CTRL + index_multi * 0x4,
+			usb_readb(acthcd->base + HCOUT1CTRL + index_multi *0x4));
+		printk(" HCOUT%dERR(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1ERR + index_multi * 0x4,
+			usb_readb(acthcd->base + HCOUT1ERR + index_multi *0x4));
+		printk(" HCOUT%dSTADDR(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1STADDR + index_multi * 0x4,
+			usb_readl(acthcd->base + HCOUT1STADDR + index_multi * 0x4));
+		printk(" HCOUT%dMAXPCK(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1MAXPCK + index_multi * 0x2,
+			usb_readw(acthcd->base + HCOUT1MAXPCK + index_multi * 0x2));
+		
+		printk(" HCOUT%dDMASTADDR(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1DMASTADDR + index_multi * 0x8,
+			usb_readl(acthcd->base + HCOUT1DMASTADDR + index_multi * 0x8));
+		printk(" HCOUT%dDMACOUNTER(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCOUT1DMACOUNTER + index_multi * 0x8,
+			usb_readl(acthcd->base + HCOUT1DMACOUNTER + index_multi * 0x8));
+	} else {
+		printk(" HCIN%dBC(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1BC + index_multi * 0x8,
+			usb_readw(acthcd->base + HCIN1BC + index_multi *0x8));
+		printk(" HCIN%dCON(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1CON+ index_multi * 0x8,
+			usb_readb(acthcd->base + HCIN1CON+ index_multi *0x8));
+		printk(" HCIN%dCS(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1CS + index_multi * 0x8,
+			usb_readb(acthcd->base + HCIN1CS + index_multi *0x8));
+		printk(" HCIN%dCS(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1CTRL + index_multi * 0x4,
+			usb_readb(acthcd->base + HCIN1CTRL+ index_multi *0x4));
+		printk(" HCIN%dERR(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1ERR + index_multi * 0x4,
+			usb_readb(acthcd->base + HCIN1ERR + index_multi *0x4));
+		printk(" HCIN%dSTADDR(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1STADDR + index_multi * 0x4,
+			usb_readl(acthcd->base + HCIN1STADDR + index_multi *0x4));
+		printk(" HCIN%dMAXPCK(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1MAXPCK + index_multi * 0x2,
+			usb_readw(acthcd->base + HCIN1MAXPCK + index_multi * 0x2));
+
+		printk(" HCIN%dDMASTADDR(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1DMASTADDR + index_multi * 0x8,
+			usb_readl(acthcd->base + HCIN1DMASTADDR + index_multi * 0x8));
+		printk(" HCIN%dDMACOUNTER(0x%p) : 0x%X\n", ep_index,
+			acthcd->base + HCIN1DMACOUNTER + index_multi * 0x8,
+			usb_readl(acthcd->base + HCIN1DMACOUNTER + index_multi * 0x8));
+	}
+
+}
+
+#ifdef AOTG_REG_DUMP
+void aotg_dbg_regs(struct aotg_hcd *acthcd)
+{
+    struct aotg_plat_data *data = acthcd->port_specific;
+#if 1
+	int i = 0;
+
+	do {
+		printk(" USB reg(0x%p):0x%X  ", acthcd->base + i, usb_readl(acthcd->base + i));
+		i += 4;
+		printk(":0x%X ", usb_readl(acthcd->base + i));
+		i += 4;
+		printk(":0x%X ", usb_readl(acthcd->base + i));
+		i += 4;
+		printk(":0x%X ", usb_readl(acthcd->base + i));
+		i += 4;
+		printk("\n");
+	} while (i < 0x600);
+#endif
+	dev_info(acthcd->dev, "============== aotg regs ==================\n");
+
+  printk("usbecs:0x%X ", usb_readl(data->usbecs));
+#if 1
+	printk(" USBEIRQ(0x%p) : 0x%X\n",
+            acthcd->base + USBEIRQ, usb_readb(acthcd->base + USBEIRQ));
+	printk(" USBEIEN(0x%p) : 0x%X\n",
+            acthcd->base + USBEIEN, usb_readb(acthcd->base + USBEIEN));
+	printk(" SRPCTRL(0x%p) : 0x%X\n",
+            acthcd->base + SRPCTRL, usb_readb(acthcd->base + SRPCTRL));
+
+	printk("HCINxSHORTPCKIRQ0(0x%p) : 0x%X\n",
+            acthcd->base + HCINxSHORTPCKIRQ0 , usb_readb(acthcd->base + HCINxSHORTPCKIRQ0 ));
+	printk("HCINxSHORTPCKIRQ1 (0x%p) : 0x%X\n",
+            acthcd->base + HCINxSHORTPCKIRQ1 , usb_readb(acthcd->base + HCINxSHORTPCKIRQ1 ));
+	printk("HCINxSHORTPCKIEN0 (0x%p) : 0x%X\n",
+            acthcd->base + HCINxSHORTPCKIEN0 , usb_readb(acthcd->base + HCINxSHORTPCKIEN0 ));
+	printk("HCINxSHORTPCKIEN1 (0x%p) : 0x%X\n",
+            acthcd->base + HCINxSHORTPCKIEN1 , usb_readb(acthcd->base + HCINxSHORTPCKIEN1 ));
+
+	printk("HCINxERRIRQ0(0x%p) : 0x%X\n",
+            acthcd->base + HCINxERRIRQ0, usb_readw(acthcd->base + HCINxERRIRQ0));
+
+	printk(" OTGIRQ(0x%p) : 0x%X\n",
+            acthcd->base + OTGIRQ, usb_readb(acthcd->base + OTGIRQ));
+	printk(" OTGSTATE(0x%p) : 0x%X\n",
+            acthcd->base + OTGSTATE, usb_readb(acthcd->base + OTGSTATE));
+	printk(" OTGCTRL(0x%p) : 0x%X\n",
+            acthcd->base + OTGCTRL, usb_readb(acthcd->base + OTGCTRL));
+	printk(" OTGSTATUS(0x%p) : 0x%X\n",
+            acthcd->base + OTGSTATUS, usb_readb(acthcd->base + OTGSTATUS));
+	printk(" OTGIEN(0x%p) : 0x%X\n",
+            acthcd->base + OTGIEN, usb_readb(acthcd->base + OTGIEN));
+	printk("\n");
+	printk(" BKDOOR(0x%p) : 0x%X\n",
+            acthcd->base + BKDOOR, usb_readb(acthcd->base + BKDOOR));
+	printk(" USBIRQ(0x%p) : 0x%X\n",
+            acthcd->base + USBIRQ, usb_readb(acthcd->base + USBIRQ));
+	printk(" USBIEN(0x%p) : 0x%X\n",
+            acthcd->base + USBIEN, usb_readb(acthcd->base + USBIEN));
+	printk("\n");
+#endif
+
+	printk("HCINxPNGIEN0:%x\n", (u32)usb_readb(acthcd->base + HCINxPNGIEN0));
+	printk(" HCIN1DMACOUNTER(0x%p) : 0x%X\n",
+            acthcd->base + HCIN1DMACOUNTER, usb_readb(acthcd->base + HCIN1DMACOUNTER));
+	printk(" HCIN2DMASTADDR(0x%p) : 0x%X\n",
+            acthcd->base + HCIN2DMASTADDR, usb_readb(acthcd->base + HCIN2DMASTADDR));
+
+	printk(" HCOUTxIRQ0(0x%p) : 0x%X\n",
+            acthcd->base + HCOUTxIRQ0, usb_readb(acthcd->base + HCOUTxIRQ0));
+	printk(" HCOUTxIEN0(0x%p) : 0x%X\n",
+            acthcd->base + HCOUTxIEN0, usb_readb(acthcd->base + HCOUTxIEN0));
+	printk(" HCINxIRQ0(0x%p) : 0x%X\n",
+            acthcd->base + HCINxIRQ0, usb_readb(acthcd->base + HCINxIRQ0));
+	printk(" HCINxIEN0(0x%p) : 0x%X\n",
+            acthcd->base + HCINxIEN0, usb_readb(acthcd->base + HCINxIEN0));
+	printk("\n");
+#if 1
+	printk(" HCIN0BC(0x%p) : 0x%X\n",
+            acthcd->base + HCIN0BC, usb_readb(acthcd->base + HCIN0BC));
+	printk(" EP0CS(0x%p) : 0x%X\n",
+            acthcd->base + EP0CS, usb_readb(acthcd->base + EP0CS));
+	printk(" HCOUT0BC(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT0BC, usb_readb(acthcd->base + HCOUT0BC));
+	printk(" HCEP0CTRL(0x%p) : 0x%X\n",
+            acthcd->base + HCEP0CTRL, usb_readb(acthcd->base + HCEP0CTRL));
+	printk("\n");
+	printk(" HCIN1BC(0x%p) : 0x%X\n",
+            acthcd->base + HCIN1BCL, usb_readw(acthcd->base + HCIN1BCL));
+	printk(" HCIN1CON(0x%p) : 0x%X\n",
+            acthcd->base + HCIN1CON, usb_readb(acthcd->base + HCIN1CON));
+	printk(" HCIN1CS(0x%p) : 0x%X\n",
+            acthcd->base + HCIN1CS, usb_readb(acthcd->base + HCIN1CS));
+	printk(" HCIN1CTRL(0x%p) : 0x%X\n",
+            acthcd->base + HCIN1CTRL, usb_readb(acthcd->base + HCIN1CTRL));
+	printk(" HCIN2BC(0x%p) : 0x%X\n",
+            acthcd->base + HCIN2BCL, usb_readw(acthcd->base + HCIN2BCL));
+	printk(" HCIN2CON(0x%p) : 0x%X\n",
+            acthcd->base + HCIN2CON, usb_readb(acthcd->base + HCIN2CON));
+	printk(" HCIN2CS(0x%p) : 0x%X\n",
+            acthcd->base + HCIN2CS, usb_readb(acthcd->base + HCIN2CS));
+	printk(" HCIN2CTRL(0x%p) : 0x%X\n",
+            acthcd->base + HCIN2CTRL, usb_readb(acthcd->base + HCIN2CTRL));
+	printk("\n");
+	printk(" HCIN4DMASTADDR(0x%p) : 0x%X\n",
+            acthcd->base + HCIN4DMASTADDR, usb_readw(acthcd->base + HCIN4DMASTADDR));
+	printk(" HCIN4DMACOUNTER(0x%p) : 0x%X\n",
+            acthcd->base + HCIN4DMACOUNTER, usb_readw(acthcd->base + HCIN4DMACOUNTER));
+	//printk(" HCINCTRL(0x%p) : 0x%X\n", acthcd->base + HCINCTRL, usb_readb(acthcd->base + HCINCTRL));
+	printk("\n");
+#endif
+	printk(" HCOUT1BC(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT1BCL, usb_readw(acthcd->base + HCOUT1BCL));
+	printk(" HCOUT1CON(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT1CON, usb_readb(acthcd->base + HCOUT1CON));
+	printk(" HCOUT1CS(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT1CS, usb_readb(acthcd->base + HCOUT1CS));
+	printk(" HCOUT1CTRL(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT1CTRL, usb_readb(acthcd->base + HCOUT1CTRL));
+	printk(" HCOUT2BC(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT2BCL, usb_readw(acthcd->base + HCOUT2BCL));
+	printk(" HCOUT2CON(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT2CON, usb_readb(acthcd->base + HCOUT2CON));
+	printk(" HCOUT2CS(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT2CS, usb_readb(acthcd->base + HCOUT2CS));
+	printk(" HCOUT2CTRL(0x%p) : 0x%X\n",
+            acthcd->base + HCOUT2CTRL, usb_readb(acthcd->base + HCOUT2CTRL));
+	printk("\n");
+	printk("\n");
+	return;
+}
+
+#else	/* AOTG_REG_DUMP */
+
+void aotg_dbg_regs(struct aotg_hcd *acthcd)
+{
+	/* fpga5209 dump */
+	printk("dump gl5209 reg\n");
+
+/*
+	printk("CMU_USBPLL(0x%p) : 0x%X\n",
+		acthcd->base + CMU_USBPLL, usb_readl(acthcd->base + CMU_USBPLL));
+	printk("CMU_DEVRST1(0x%p) : 0x%X\n",
+		acthcd->base + CMU_DEVRST1, usb_readl(acthcd->base + CMU_DEVRST1));
+	printk("HCDMABCKDOOR(0x%p) : 0x%X\n",
+		acthcd->base + HCDMABCKDOOR, usb_readl(acthcd->base + HCDMABCKDOOR));
+	printk("USBH_0ECS(0x%p) : 0x%X\n",
+		acthcd->base + USBH_0ECS, usb_readl(acthcd->base + USBH_0ECS));	
+*/
+	printk(" USBEIEN(0x%p) : 0x%X\n",
+            acthcd->base + USBEIEN, usb_readb(acthcd->base + USBEIEN));
+	printk(" OTGIRQ(0x%p) : 0x%X\n",
+            acthcd->base + OTGIRQ, usb_readb(acthcd->base + OTGIRQ));
+	printk(" OTGSTATE(0x%p) : 0x%X\n",
+            acthcd->base + OTGSTATE, usb_readb(acthcd->base + OTGSTATE));
+	printk(" OTGCTRL(0x%p) : 0x%X\n",
+            acthcd->base + OTGCTRL, usb_readb(acthcd->base + OTGCTRL));
+	printk(" OTGSTATUS(0x%p) : 0x%X\n",
+            acthcd->base + OTGSTATUS, usb_readb(acthcd->base + OTGSTATUS));
+	printk(" OTGIEN(0x%p) : 0x%X\n",
+            acthcd->base + OTGIEN, usb_readb(acthcd->base + OTGIEN));
+
+    return;
+}
+
+#endif	/* AOTG_REG_DUMP */
+
+
+#ifdef AOTG_DEBUG_FILE
+
+int aotg_dbg_proc_output_ep_state1(struct aotg_hcd *acthcd)
+{
+	struct aotg_hcep *tmp_ep;
+	int i;
+	struct aotg_queue *q, *next;
+	struct aotg_hcep *ep;
+	struct urb *urb;
+
+	ep = acthcd->active_ep0;
+	if (ep) {
+		printk("------------- active ep0 queue: \n");
+		printk("urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+		printk("urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+		printk("urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+		printk("urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+
+		if (ep->q != NULL) {
+			q = ep->q;
+			printk("dma[0]: ep->index: %d, type: %d, dir : %s, transfer_buffer_length: %d, actual_length:%d\n",
+				q->ep->index,
+				usb_pipetype(q->urb->pipe), usb_pipeout(q->urb->pipe)?"out":"in",
+				q->urb->transfer_buffer_length, q->urb->actual_length);
+		}
+	}
+
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->ep0[i];
+		if (ep) {
+			printk("------------- ep0 list index:%d queue: \n", i);
+			printk("urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+			printk("urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+			printk("urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+			printk("urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+			printk("ep->epnum:%d\n", ep->epnum);
+
+			if (ep->q != NULL) {
+				q = ep->q;
+				printk("ep->index: %d, type: %d, dir : %s, transfer_buffer_length: %d, actual_length:%d\n",
+					q->ep->index,
+					usb_pipetype(q->urb->pipe), usb_pipeout(q->urb->pipe)?"out":"in",
+					q->urb->transfer_buffer_length, q->urb->actual_length);
+			}
+		}
+	}
+
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		tmp_ep = acthcd->inep[i];
+		if (tmp_ep) {
+			//if (tmp_ep->urb_enque_cnt > (tmp_ep->urb_endque_cnt + tmp_ep->urb_stop_stran_cnt)) 
+			{
+				printk("inep:%d\n", i);
+				printk("urb_enque_cnt:%d\n", tmp_ep->urb_enque_cnt);
+				printk("urb_endque_cnt:%d\n", tmp_ep->urb_endque_cnt);
+				printk("urb_stop_stran_cnt:%d\n", tmp_ep->urb_stop_stran_cnt);
+				printk("urb_unlinked_cnt:%d\n", tmp_ep->urb_unlinked_cnt);
+
+				printk("index:%d\n", tmp_ep->index);
+				printk("maxpacket:%d\n", tmp_ep->maxpacket);
+				printk("epnum:%d\n", tmp_ep->epnum);
+			}
+		}
+	}
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		tmp_ep = acthcd->outep[i];
+		if (tmp_ep) {
+			//if (tmp_ep->urb_enque_cnt > (tmp_ep->urb_endque_cnt + tmp_ep->urb_stop_stran_cnt)) 
+			{
+				printk("outep:%d\n", i);
+				printk("urb_enque_cnt:%d\n", tmp_ep->urb_enque_cnt);
+				printk("urb_endque_cnt:%d\n", tmp_ep->urb_endque_cnt);
+				printk("urb_stop_stran_cnt:%d\n", tmp_ep->urb_stop_stran_cnt);
+				printk("urb_unlinked_cnt:%d\n", tmp_ep->urb_unlinked_cnt);
+
+				printk("index:%d\n", tmp_ep->index);
+				printk("maxpacket:%d\n", tmp_ep->maxpacket);
+				printk("epnum:%d\n", tmp_ep->epnum);
+			}
+		}
+	}
+
+	printk("in hcd enqueue list: \n");
+	list_for_each_entry_safe(q, next, &acthcd->hcd_enqueue_list, enqueue_list) {
+		urb = q->urb;
+		ep = q->ep;
+		printk("ep->epnum:%d ", ep->epnum);
+		printk("urb->transfer_buffer_length:%d ", urb->transfer_buffer_length);
+		printk("usb_pipein(urb->pipe):%x\n", usb_pipein(urb->pipe));
+		printk("usb_pipetype(urb->pipe):%x\n", usb_pipetype(urb->pipe));
+	}
+	return 0;
+}
+
+int aotg_dbg_proc_output_ep_state(struct aotg_hcd *acthcd)
+{
+	struct aotg_queue *q, *next;
+	struct aotg_hcep *ep;
+	struct urb *urb;
+	int i = 0;
+
+	list_for_each_entry_safe(q, next, &acthcd->hcd_enqueue_list, enqueue_list) {
+		urb = q->urb;
+		ep = q->ep;
+		i++;
+	}
+
+	if (i>2) {
+		printk("error, more enque.\n");
+		//aotg_dbg_output_info();
+		//aotg_dbg_regs(acthcd);
+		//BUG_ON(1);
+	}
+	if (i <= 1) {
+		i = 0;
+	}
+	aotg_dbg_proc_output_ep_state1(acthcd);
+	return i;
+}
+
+int aotg_dump_regs(struct aotg_hcd *acthcd)
+{
+	int i;
+	struct aotg_hcep *ep;
+
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->inep[i];
+		if (ep) {
+			aotg_dump_linklist_reg_2(acthcd, ep->mask);
+		}
+	}
+
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->outep[i];
+		if (ep) {
+			aotg_dump_linklist_reg_2(acthcd, ep->mask);	
+		}
+	}
+
+	return 0;
+
+}
+
+void __dump_ring_info(struct aotg_hcep *ep)
+{
+	int i;
+	struct aotg_ring *ring = NULL;
+	struct aotg_td *td, *next;
+	struct urb *urb;
+	struct aotg_trb *trb;
+
+	//struct aotg_trb trb_val;
+
+	if (!ep)
+		return;
+	printk("\n------------- current %s ep%d ring : \n", ep->is_out ? "OUT" : "IN",
+					ep->index);
+	printk("urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+	printk("urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+	printk("urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+	printk("urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+	printk("ep_num:%d\n", ep->epnum);
+	printk("ep_type:%d\n", ep->type);
+
+	ring = ep->ring;
+	
+	i=0;
+	if (ring) {
+		trb = ring->first_trb;
+		while(trb <= ring->last_trb) {
+			printk("%d hw_buf_ptr:%x,hw_buf_len:%x,hw_buf_remain:%x,hw_token:%x\n",i, \
+			       trb->hw_buf_ptr,trb->hw_buf_len,trb->hw_buf_remain,trb->hw_token);
+			trb++;
+			i++;
+		}
+		
+	}
+	
+	if (ring) {		
+		printk("-----\n");
+		printk("enring_cnt:%d\n", ring->enring_cnt);
+		printk("dering_cnt:%d\n", ring->dering_cnt);
+		printk("num_trbs_free:%d\n", (u32)atomic_read(&ring->num_trbs_free));
+		printk("first_trb:0x%p, dma:0x%x\n", ring->first_trb, 
+					ring_trb_virt_to_dma(ring, ring->first_trb));
+		printk("last_trb:0x%x, dma:0x%x\n", (u32)(ring->last_trb),
+					ring_trb_virt_to_dma(ring, ring->last_trb));
+		printk("ring_enqueue:0x%x(%d)\n", (u32)(ring->enqueue_trb),
+					ring->enqueue_trb - ring->first_trb);
+		printk("ring_dequeue:0x%x(%d)\n", (u32)(ring->dequeue_trb),
+					ring->dequeue_trb - ring->first_trb);
+		printk("reg_linkaddr(0x%p):0x%x\n", ring->reg_dmalinkaddr,
+					usb_readl(ring->reg_dmalinkaddr));
+		printk("reg_curradr(0x%p):0x%x\n", ring->reg_curaddr,
+					usb_readl(ring->reg_curaddr));
+		printk("reg_dmactrl(0x%p):0x%x\n", ring->reg_dmactrl,
+					usb_readl(ring->reg_dmactrl));
+
+		printk( "in eq_enqueue_td list: \n");
+		i = 0;
+		list_for_each_entry_safe(td, next, &ep->queue_td_list, queue_list) {
+			urb = td->urb;	
+			i++;
+			printk("-----\n");
+			printk("urb->transfer_buffer_length:%d\n", urb->transfer_buffer_length);
+			printk("usb_pipein(urb->pipe):%x\n", usb_pipein(urb->pipe));
+			printk("usb_pipetype(urb->pipe):%x\n", usb_pipetype(urb->pipe));
+		}
+		if (i) {
+			i = 0;
+			printk("======td in queue num : %d\n", i);
+		}
+
+		printk( "in eq_enring_td list: \n");
+		list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+			//trb_val = *(td->trb_vaddr);
+			printk("-----\n");
+			i++;
+			trb = td->trb_vaddr;
+			if (td->urb)
+				printk("urb:%p\n",td->urb);
+			printk("hw_buf_ptr:%x,hw_buf_len:%x,hw_buf_remain:%x,hw_token:%x\n", \
+			       trb->hw_buf_ptr,trb->hw_buf_len,trb->hw_buf_remain,trb->hw_token);
+			printk("num_trbs:%d\n", td->num_trbs);
+			//printk("trb_dma:0x%x\n", td->trb_dma);
+			//printk("trb_vaddr:0x%x\n", td->trb_vaddr);
+			//printk("trb_dma:0x%x\n", td->trb_dma);
+			//printk("cross_ring:0x%d\n", td->cross_ring);
+
+			//aotg_hcd_dump_td(ring, td);
+			//printk("hw_buf_ptr : 0x%x\n", trb_val.hw_buf_ptr);
+			//printk("hw_buf_len : %d\n", trb_val.hw_buf_len);
+			//printk("hw_buf_remain : %d\n", trb_val.hw_buf_remain);
+			//printk("hw_token : 0x%x\n", trb_val.hw_token);	
+			//printk("in_dma_irq:0x%x\n",usb_readw(USBH_BASE0 + HCINxDMAIRQ0));
+		}
+		if (i) {
+			printk("======td in ring num : %d\n", i);
+		}
+	}
+ 
+/*
+	seq_printf(s, "------------- current IN ep%d ring : \n", i);
+	seq_printf(s, "urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+	seq_printf(s, "urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+	seq_printf(s, "urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+	seq_printf(s, "urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+	seq_printf(s, "ep->epnum:%d\n", ep->epnum);
+
+	ring = ep->ring;
+	if (ring) {
+		seq_printf(s, "enring_cnt:%d\n", ring->enring_cnt);
+		seq_printf(s, "dering_cnt:%d\n", ring->dering_cnt);
+		seq_printf(s, "num_trbs_free:%d\n", ring->num_trbs_free);
+		seq_printf(s, "ring_enqueue_ptr:0x%x", ring->enqueue_trb);
+		seq_printf(s, "ring_dequeue_ptr:0x%x", ring->dequeue_trb);
+
+		seq_printf(s, "in eq_enqueue_td list: \n");
+		list_for_each_entry_safe(td, next, &ep->queue_td_list, queue_td_list) {
+			urb = td->urb;
+			seq_printf(s, "urb->transfer_buffer_length:%d ", urb->transfer_buffer_length);
+			seq_printf(s, "usb_pipein(urb->pipe):%x\n", usb_pipein(urb->pipe));
+			seq_printf(s, "usb_pipetype(urb->pipe):%x\n", usb_pipetype(urb->pipe));
+		}
+
+		seq_printf(s, "in eq_enring_td list: \n");
+		list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+			seq_printf(s, "num_trbs:%d\n", td->num_trbs);
+			seq_printf(s, "trb_vaddr:0x%x\n", td->trb_vaddr);
+			seq_printf(s, "trb_dma:0x%x\n", td->trb_dma);
+			seq_printf(s, "cross_ring:0x%d\n", td->cross_ring);
+		}
+	}
+*/
+}
+
+static int aotg_hcd_show_ring_info(struct aotg_hcd *acthcd)
+{
+	int i;
+	struct aotg_hcep *ep;
+	struct aotg_queue *q;
+
+	ep = acthcd->active_ep0;
+	if (ep) {
+		printk("------------- active ep0 queue: \n");
+		printk("urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+		printk("urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+		printk("urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+		printk("urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+
+		if (ep->q != NULL) {
+			q = ep->q;
+			printk("dma[0]: ep->index: %d, type: %d, dir : %s, transfer_buffer_length: %d, actual_length:%d\n",
+				q->ep->index,
+				usb_pipetype(q->urb->pipe), usb_pipeout(q->urb->pipe)?"out":"in",
+				q->urb->transfer_buffer_length, q->urb->actual_length);
+		}
+	}
+
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->inep[i];
+		__dump_ring_info(ep);
+	}
+
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->outep[i];
+		__dump_ring_info(ep);
+	}
+
+	return 0;
+}
+#if 0
+static int aotg_hcd_show_enque_info(struct seq_file *s, struct aotg_hcd	*acthcd)
+{
+	int i;
+	struct aotg_queue *q, *next;
+	struct aotg_hcep *ep;
+
+	for (i = 0; i < AOTG_QUEUE_POOL_CNT; i++) {
+		if (acthcd->queue_pool[i] != NULL) {
+			seq_printf(s, "queue_pool[%d]->in_using: %d\n", 
+			      	i, acthcd->queue_pool[i]->in_using);
+		} 
+	}
+
+	seq_printf(s, "current dma queue: \n");
+
+	ep = acthcd->active_ep0;
+	if (ep) {
+		seq_printf(s, "------------- active ep0 queue: \n");
+		seq_printf(s, "urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+		seq_printf(s, "urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+		seq_printf(s, "urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+		seq_printf(s, "urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+
+		if (ep->q != NULL) {
+			q = ep->q;
+			seq_printf(s, "dma[0]: ep->index: %d, type: %d, dir : %s, transfer_buffer_length: %d, actual_length:%d\n",
+				q->ep->index,
+				usb_pipetype(q->urb->pipe), usb_pipeout(q->urb->pipe)?"out":"in",
+				q->urb->transfer_buffer_length, q->urb->actual_length);
+		}
+	}
+
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->ep0[i];
+		if (ep) {
+			seq_printf(s, "------------- ep0 list index:%d queue: \n", i);
+			seq_printf(s, "urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+			seq_printf(s, "urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+			seq_printf(s, "urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+			seq_printf(s, "urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+			seq_printf(s, "ep->epnum:%d\n", ep->epnum);
+
+			if (ep->q != NULL) {
+				q = ep->q;
+				seq_printf(s, "ep->index: %d, type: %d, dir : %s, transfer_buffer_length: %d, actual_length:%d\n",
+					q->ep->index,
+					usb_pipetype(q->urb->pipe), usb_pipeout(q->urb->pipe)?"out":"in",
+					q->urb->transfer_buffer_length, q->urb->actual_length);
+			}
+		}
+	}
+	
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->inep[i];
+		if (ep) {
+			seq_printf(s, "------------- current IN ep%d queue: \n", i);
+			seq_printf(s, "urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+			seq_printf(s, "urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+			seq_printf(s, "urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+			seq_printf(s, "urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+			seq_printf(s, "ep->epnum:%d\n", ep->epnum);
+
+			if (ep->q != NULL) {
+				q = ep->q;
+				seq_printf(s, "ep->index: %d, type: %d, dir : %s, transfer_buffer_length: %d, actual_length:%d\n",
+					q->ep->index,
+					usb_pipetype(q->urb->pipe), usb_pipeout(q->urb->pipe)?"out":"in",
+					q->urb->transfer_buffer_length, q->urb->actual_length);
+			}
+		}
+	}
+	
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->outep[i];
+		if (ep) {
+			seq_printf(s, "------------- current OUT ep%d queue: \n", i);
+			seq_printf(s, "urb_enque_cnt:%d\n", ep->urb_enque_cnt);
+			seq_printf(s, "urb_endque_cnt:%d\n", ep->urb_endque_cnt);
+			seq_printf(s, "urb_stop_stran_cnt:%d\n", ep->urb_stop_stran_cnt);
+			seq_printf(s, "urb_unlinked_cnt:%d\n", ep->urb_unlinked_cnt);
+			seq_printf(s, "ep->epnum:%d\n", ep->epnum);
+
+			if (ep->q != NULL) {
+				q = ep->q;
+				seq_printf(s, "ep->index: %d, type: %d, dir : %s, transfer_buffer_length: %d, actual_length:%d\n",
+					q->ep->index,
+					usb_pipetype(q->urb->pipe), usb_pipeout(q->urb->pipe)?"out":"in",
+					q->urb->transfer_buffer_length, q->urb->actual_length);
+			}
+		}
+	}
+
+	seq_printf(s, "\n");
+	seq_printf(s, "in hcd enqueue list: \n");
+	list_for_each_entry_safe(q, next, &acthcd->hcd_enqueue_list, enqueue_list) {
+		ep = q->ep;
+		seq_printf(s, "ep->epnum:%d ", ep->epnum);
+		seq_printf(s, "urb->transfer_buffer_length:%d ", q->urb->transfer_buffer_length);
+		seq_printf(s, "usb_pipein(urb->pipe):%x\n", usb_pipein(q->urb->pipe));
+		seq_printf(s, "usb_pipetype(urb->pipe):%x\n", usb_pipetype(q->urb->pipe));
+	}
+	return 0;
+}
+#endif
+/* 
+ * echo a value to controll the cat /proc/aotg_hcd output content.
+ * echo h>/proc/aotg_hcd.0 to see help info.
+ */
+ssize_t aotg_hcd_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	char c = 'n';
+
+	if (count) {
+		if (get_user(c, buf))
+			return -EFAULT;
+		aotg_hcd_proc_sign = c;
+	}
+	if (c == 'h') {
+		printk(" a ---- all.  \n");
+		printk(" b ---- backup info.  \n");
+		printk(" d ---- dma related.  \n");
+		printk(" e ---- enque and outque info.  \n");
+		printk(" f ---- trace in info.  \n");
+		printk(" h ---- help info.  \n");
+		printk(" n ---- normal.  \n");
+		printk(" r ---- register info.  \n");
+		printk(" s ---- aotg state.  \n");
+		printk(" t ---- trace out info.  \n");
+		printk(" z ---- stop stace.  \n");
+	}
+        return count;
+}
+
+int aotg_hcd_proc_show(struct seq_file *s, void *unused)
+{
+	struct aotg_hcd	*acthcd = s->private;
+	struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+	//struct aotg_plat_data *data = acthcd->port_specific;
+
+	if (aotg_hcd_proc_sign == 'd') {
+		// todo.
+	}
+
+	if (aotg_hcd_proc_sign == 's') {
+		aotg_dbg_proc_output_ep_state(acthcd);
+		seq_printf(s, "hcd state : 0x%08X\n", hcd->state);
+	}
+
+	if (aotg_hcd_proc_sign == 'r') {
+		//aotg_dbg_regs(acthcd);
+		aotg_dump_regs(acthcd);
+	}
+
+	if (aotg_hcd_proc_sign == 'e') {
+		//aotg_hcd_show_enque_info(s, acthcd);
+		aotg_hcd_show_ring_info(acthcd);
+	}
+
+	if (aotg_hcd_proc_sign == 'b') {
+		aotg_dbg_proc_output_ep();
+		aotg_dbg_output_info();
+	}
+
+	if (aotg_hcd_proc_sign == 'a') {
+	}
+
+	seq_printf(s, "\n");
+	return 0;
+}
+
+
+static int aotg_hcd_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, aotg_hcd_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations proc_ops = {
+	.open		= aotg_hcd_proc_open,
+	.read		= seq_read,
+	.write		= aotg_hcd_proc_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+void create_debug_file(struct aotg_hcd *acthcd)
+{
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+
+	acthcd->pde = proc_create_data(dev_name(dev), 0, NULL, &proc_ops, acthcd);
+	return;
+}
+
+void remove_debug_file(struct aotg_hcd *acthcd)
+{
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+	
+	if (acthcd->pde)
+		remove_proc_entry(dev_name(dev), NULL);
+	return;
+}
+
+#else	/* AOTG_DEBUG_FILE */
+
+void create_debug_file(struct aotg_hcd *acthcd)
+{
+	return;
+}
+
+void remove_debug_file(struct aotg_hcd *acthcd)
+{
+	return;
+}
+
+#endif	/* AOTG_DEBUG_FILE */
+
+
+void aotg_print_xmit_cnt(char * info, int cnt)
+{
+	if (aotg_hcd_proc_sign == 'e') {
+		printk("%s cnt:%d\n", info, cnt);
+	}
+	//printk("\n");
+	//aotg_dbg_proc_output_ep();
+	//aotg_dbg_regs(p_aotg_hcd0);
+	//aotg_dbg_output_info();
+
+	return;
+}
+//EXPORT_SYMBOL(aotg_print_xmit_cnt);
+
+
+static struct proc_dir_entry *acts_hub_pde = NULL; 
+
+int acts_hcd_proc_show(struct seq_file *s, void *unused)
+{
+	seq_printf(s, "hcd_ports_en_ctrl: %d\n", hcd_ports_en_ctrl);
+	return 0;
+}
+
+static int acts_hub_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, acts_hcd_proc_show, PDE(inode)->data);
+}
+
+static ssize_t acts_hub_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	char c = 'n';
+
+	if (count) {
+		if (get_user(c, buf))
+			return -EFAULT;
+	}
+	if ((c >= '0') && (c <= '3')) { 
+		hcd_ports_en_ctrl = c - '0';
+		printk("hcd_hub en:%d\n", hcd_ports_en_ctrl);
+	}
+	if (c == 'h') {
+		printk(" num ---- 0-all enable, 1-usb0 enable, 2-usb1 enable, 3-reversed. \n");
+		printk("o ---- hcd_hub power on\n");
+		printk("f ---- hcd_hub power off\n");
+		printk("a ---- hcd_hub aotg0 add\n");
+		printk("b ---- hcd_hub aotg0 remove\n");
+		printk("c ---- hcd_hub aotg1 add\n");
+		printk("d ---- hcd_hub aotg1 remove\n");
+	}
+
+	if (c == 'a') {
+		printk("hcd_hub aotg0 add\n");
+		//aotg0_device_init(0);
+		aotg_hub_register(0);
+	}
+	if (c == 'b') {
+		printk("hcd_hub aotg0 remove\n");
+		//aotg0_device_exit(0);
+		aotg_hub_unregister(0);
+	}
+
+	if (c == 'c') {
+		printk("hcd_hub aotg1 add\n");
+		//aotg1_device_init(0);
+		aotg_hub_register(1);
+	}
+	if (c == 'd') {
+		printk("hcd_hub aotg1 remove\n");
+		//aotg1_device_exit(0);
+		aotg_hub_unregister(1);
+	}
+
+	if (c == 'e') {
+		aotg_trace_onff = 1;
+	}
+	if (c == 'f') {
+		aotg_trace_onff = 0;
+	}
+	
+	if (c == 'g') {
+		aotg_dbg_regs(act_hcd_ptr[0]); 
+	}
+	
+	if (c == 'i') {
+		aotg_dbg_regs(act_hcd_ptr[1]); 
+	}
+		return count;
+}
+
+static const struct file_operations acts_hub_proc_ops = {
+	.open		= acts_hub_proc_open,
+	.read		= seq_read,
+	.write		= acts_hub_proc_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+void create_acts_hcd_proc(void)
+{
+	acts_hub_pde = proc_create_data("acts_hub", S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | S_IROTH|S_IWOTH, NULL, &acts_hub_proc_ops, acts_hub_pde);
+	return;
+}
+
+void remove_acts_hcd_proc(void)
+{
+	if (acts_hub_pde) {
+		remove_proc_entry("acts_hub", NULL);
+		acts_hub_pde = NULL;
+	}
+	return;
+}
+
diff --git a/drivers/usb/host/aotg_debug.h b/drivers/usb/host/aotg_debug.h
new file mode 100644
index 0000000..73493da
--- /dev/null
+++ b/drivers/usb/host/aotg_debug.h
@@ -0,0 +1,88 @@
+#ifndef  __LINUX_USB_AOTG_DEBUG_H__ 
+#define  __LINUX_USB_AOTG_DEBUG_H__ 
+
+//#define DEBUG_HCD
+//#define DEBUG_HUB
+//#define DEBUG_SETUP_DATA
+//#define DEBUG_EP_CONFIG
+//#define IN_PROCESS_DEBUG
+//#define DEBUG_IN_DATA
+//#define OUT_PROCESS_DEBUG
+//#define DEBUG_OUT_DATA
+//#define DEBUG_DMA
+#define AOTG_REG_DUMP
+//#define AOTG_DEBUG_RECORD_URB
+#define AOTG_DEBUG_FILE
+#define DEBUG_LINKLIST_DMA
+
+#define ACT_HCD_ERR		printk("%s:%d, err!\n", __func__, __LINE__);
+#define ACT_HCD_DBG		printk("%s:%d, dbg!\n", __func__, __LINE__);
+
+#ifdef  ERR
+#undef  ERR
+#endif
+#define ERR(fmt, args...) printk(KERN_ERR fmt, ## args)
+
+#ifdef DEBUG_HUB
+#define HUB_DEBUG(fmt, args...) printk(KERN_ERR fmt, ## args)
+#else
+#define HUB_DEBUG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_HCD
+#define HCD_DEBUG(fmt, args...) printk(KERN_ERR fmt, ## args)
+#else
+#define HCD_DEBUG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef IN_PROCESS_DEBUG  //ep1, ep2
+#define IN_DEBUG(fmt, args...) printk(KERN_ERR fmt, ## args)
+#else
+#define IN_DEBUG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef  OUT_PROCESS_DEBUG
+#define OUT_DEBUG(fmt, args...) printk(KERN_ERR fmt, ## args)
+#else
+#define OUT_DEBUG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_DMA
+#define ACT_DMA_DEBUG(fmt, args...) printk(KERN_ERR fmt, ## args)
+#else
+#define ACT_DMA_DEBUG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_LINKLIST_DMA
+#define ACT_LINKLIST_DMA_DEBUG(fmt, args...) printk(KERN_ERR fmt, ## args)
+#else
+#define ACT_LINKLIST_DMA_DEBUG(fmt,args...) do {} while(0)
+#endif
+
+#define HCD_WARN(fmt, args...) printk(KERN_WARNING fmt, ## args)
+#define HCD_WARNING(fmt, args...) printk(KERN_WARNING fmt, ## args)
+
+extern unsigned int aotg_trace_onff;
+#define	AOTG_TRACE_ERR_PLACE	if (aotg_trace_onff) printk("-%d\n", __LINE__);
+
+void aotg_dbg_put_info(char *info0, unsigned int info1, unsigned int info2, unsigned int info3);
+void aotg_dbg_output_info(void);
+
+void aotg_dbg_put_q(struct aotg_queue *q, unsigned int num, unsigned int type, unsigned int len);
+void aotg_dbg_finish_q(struct aotg_queue *q);
+
+void aotg_dbg_proc_output_ep(void);
+int aotg_dbg_proc_output_ep_state(struct aotg_hcd *acthcd);
+
+void create_debug_file(struct aotg_hcd *acthcd);
+void remove_debug_file(struct aotg_hcd *acthcd);
+
+void aotg_dbg_regs(struct aotg_hcd *acthcd);
+
+void create_acts_hcd_proc(void);
+void remove_acts_hcd_proc(void);
+void aotg_dump_ep_reg(struct aotg_hcd *acthcd, int ep_index, int is_out);
+
+
+#endif /* __LINUX_USB_AOTG_DEBUG_H__ */ 
+ 
diff --git a/drivers/usb/host/aotg_hcd.c b/drivers/usb/host/aotg_hcd.c
new file mode 100644
index 0000000..c14c89a
--- /dev/null
+++ b/drivers/usb/host/aotg_hcd.c
@@ -0,0 +1,4168 @@
+/*
+ * (C) Copyright www.actions-semi.com 2012-2014
+ *     Written by houjingkun. <houjingkun at actions-semi.com>
+ * 
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/kthread.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+
+#include <asm/irq.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/hardware.h>
+#include <linux/clk.h>
+#include <linux/wakelock.h>
+#include <linux/suspend.h>
+#include <mach/debug.h>
+#include <asm/prom.h>
+#include <mach/gpio.h>
+#include <linux/kallsyms.h>
+#include <mach/powergate.h>
+#include <mach/module-owl.h>
+
+#include "aotg_hcd.h"
+#include "aotg_plat_data.h"
+#include "aotg_debug.h"
+#include "aotg_mon.h"
+
+static int aotg0_slew_rate = -1;
+module_param(aotg0_slew_rate, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(aotg0_slew_rate, "aotg0_slew_rate");
+static int aotg0_tx_bias = -1;
+module_param(aotg0_tx_bias, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(aotg0_tx_bias, "aotg0_tx_bias");
+
+static int aotg1_slew_rate = -1;
+module_param(aotg1_slew_rate, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(aotg1_slew_rate, "aotg1_slew_rate");
+static int aotg1_tx_bias = -1;
+module_param(aotg1_tx_bias, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(aotg1_tx_bias, "aotg1_tx_bias");
+
+#define	DRIVER_DESC	"AOTG USB Host Controller Driver"
+
+struct aotg_hcd *act_hcd_ptr[2] = {NULL};
+
+static int handle_setup_packet(struct aotg_hcd *acthcd, struct aotg_queue *q);
+static void handle_hcep0_in(struct aotg_hcd *acthcd);
+static void handle_hcep0_out(struct aotg_hcd *acthcd);
+//static int aotg_hcd_flush_queue(struct aotg_hcd *acthcd);
+#if 0
+#ifdef	CONFIG_PM
+static void aotg_hcd_register_earlysuspend(struct aotg_hcd *acthcd);
+static void aotg_hcd_unregister_earlysuspend(struct aotg_hcd *acthcd);
+static void aotg_hcd_early_suspend(struct early_suspend *h);
+static void aotg_hcd_late_resume(struct early_suspend *h);
+
+typedef int (* aotg_hcd_reset_device_f)(struct usb_device *udev);
+aotg_hcd_reset_device_f aotg_hcd_reset_device = NULL;
+void aotg_hcd_reset_and_verify_device(struct aotg_hcd *acthcd, int reset_device);
+#endif
+#endif
+
+#define MAX_PACKET(x)	((x)&0x7FF)
+
+/* because usb0 and usb1's pll is all controlled together, 
+ * we couldn't enable aotg0 and aotg1 seperately. 
+ */
+//static int hcd_2clk_bits_en = 0;
+/* 0 is all enable, 1 -- just usb0 enable, 2 -- usb1 enable, 
+ * 3 -- usb0 and usb1 enable,but reversed. 
+ */
+int hcd_ports_en_ctrl = 0;
+//static unsigned int aotg_registered_map = 0;
+int vbus_otg_en_gpio[2][2];
+static struct platform_device *aotg_dev[2] = {NULL};
+static int aotg_initialized[2] = {0};
+int is_ls_device[2] = {0}; /*if detect low speed device plug in,must disable usbh high speed*/
+struct mutex aotg_onoff_mutex;
+
+static u64 hcd_dmamask = DMA_BIT_MASK(32);
+static struct aotg_plat_data aotg_data0 = {
+	.usbecs = (void __iomem *)IO_ADDRESS(USBH0_ECS),
+	.usbpll = (void __iomem *)IO_ADDRESS(CMU_USBPLL),
+	.usbpll_bits = CMU_USBPLL_USBPLL0EN,
+	.devrst = (void __iomem *)IO_ADDRESS(CMU_DEVRST1),
+	.devrst_bits = CMU_DEVRST1_USBH0,
+	.no_hs = 0,
+};
+
+static struct aotg_plat_data aotg_data1 = {
+	.usbecs = (void __iomem *)IO_ADDRESS(USBH1_ECS),
+	.usbpll = (void __iomem *)IO_ADDRESS(CMU_USBPLL),
+	.usbpll_bits = CMU_USBPLL_USBPLL1EN,
+	.devrst = (void __iomem *)IO_ADDRESS(CMU_DEVRST1),
+	.devrst_bits = CMU_DEVRST1_USB1,
+	.no_hs = 0,
+};
+#if 0
+/* forbid to enter suspend when driver is installed. */
+//struct wake_lock acts_hcd_wakelock;
+
+#ifdef	CONFIG_PM
+
+static void aotg_hcd_register_earlysuspend(struct aotg_hcd *acthcd)
+{
+	if (!acthcd) {
+		ACT_HCD_ERR
+		return;
+	}
+	
+	acthcd->earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 10;
+	acthcd->earlysuspend.suspend = aotg_hcd_early_suspend;
+	acthcd->earlysuspend.resume = aotg_hcd_late_resume;
+	register_early_suspend(&acthcd->earlysuspend);
+	
+	acthcd->lr_flag = 0;
+	
+	return;
+}
+
+static void aotg_hcd_unregister_earlysuspend(struct aotg_hcd *acthcd)
+{
+	if (acthcd->earlysuspend.suspend) 
+		unregister_early_suspend(&acthcd->earlysuspend);
+
+	acthcd->earlysuspend.suspend = NULL;
+	acthcd->earlysuspend.resume = NULL;
+	
+	return;
+}
+
+static void aotg_hcd_early_suspend(struct early_suspend *h)
+{
+	printk(KERN_DEBUG"%s do nothing!\n", __FUNCTION__);
+	
+	return;
+}
+
+static void aotg_hcd_late_resume(struct early_suspend *h)
+{
+	struct aotg_hcd *acthcd = container_of(h, struct aotg_hcd, earlysuspend);
+	if (!acthcd) {
+		printk(KERN_ERR"%s err, acthcd is NULL pointer!\n", __FUNCTION__);
+		return;
+	}
+	
+	if (acthcd->lr_flag) {
+		acthcd->lr_flag = 0;
+		printk(KERN_DEBUG"%s, %d\n", __FUNCTION__, __LINE__);
+//		if(hcd_suspend_en==0)
+			aotg_hcd_reset_and_verify_device(acthcd, USB_RESET_AND_VERIFY_DEVICE);
+	}
+	
+	return;
+}
+
+#if 0
+static void aotg_hcd_resume_disconnect(struct aotg_hcd *acthcd)
+{
+	//printk("uhost%d, usb device inserted : %d, otg state : 0x%02X\n",	acthcd->id, acthcd->inserted, usb_readb(acthcd->base + OTGSTATE) );
+	if ( (acthcd->inserted ==1) && 
+	    (usb_readb(acthcd->base + OTGSTATE) != AOTG_STATE_A_HOST)) {
+		printk("uhost%d,usb device disconnect in suspend, so,  now disconnect it!\n", acthcd->id);
+		acthcd->discon_happened = 1;
+		mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(1));
+	}
+}
+#endif
+
+void aotg_hcd_reset_and_verify_device(struct aotg_hcd *acthcd, int reset_device)
+{	
+	int i, ret = 0;
+	unsigned long jiffies_expire = jiffies + HZ;
+	struct usb_device *udev = NULL;
+	
+	printk (KERN_DEBUG"* %s, %d *\n", __FUNCTION__, __LINE__);
+		
+	if (acthcd == NULL){
+		ACT_HCD_ERR
+		return;
+	}
+	
+	for (i = 0; i < MAX_EP_NUM; i++) {
+			if (acthcd->ep0[i] != NULL) {
+				break;
+			}
+		}
+	
+	if (i == MAX_EP_NUM) {
+		printk(KERN_ERR"%s, usb device is NULL!\n", __FUNCTION__);
+	}
+	else
+		udev = acthcd->ep0[i]->udev;
+
+	if (udev == NULL) {
+		printk(KERN_ERR"%s, udev is NULL, can't reset device here!\n", __FUNCTION__);
+		return;
+	}
+
+	while (!usb_trylock_device(udev)) {
+		if (time_after(jiffies, jiffies_expire)){
+			ret = -1;
+			break;
+		}
+		msleep(15);
+	}
+	
+	if (ret == 0) {
+		if (reset_device){
+			printk (KERN_DEBUG"usb_reset_and_verify_device\n");
+			aotg_hcd_reset_device = (aotg_hcd_reset_device_f)kallsyms_lookup_name("usb_reset_and_verify_device");
+			if (aotg_hcd_reset_device != NULL)
+				aotg_hcd_reset_device(udev);
+			else 
+				printk(KERN_ERR"Get reset_device fail!\n");
+		} else {
+				printk (KERN_DEBUG"usb_reset_device\n");
+				usb_reset_device(udev);		
+		}
+		mutex_unlock(&(udev->dev).mutex);
+	} else {
+		printk (KERN_ERR"Fail to reset usb device!\n");
+	}
+}
+
+EXPORT_SYMBOL_GPL (aotg_hcd_reset_and_verify_device);
+#endif
+#endif
+
+typedef void (* aotg_hub_symbol_func_t)(int);
+aotg_hub_symbol_func_t aotg_hub_notify_func = NULL;
+
+void aotg_power_onoff(int id,int on_off)
+{
+	if(port_host_plug_detect[id] == 2)
+		return;
+	if(port_host_plug_detect[id] == 3){
+		if(act_hcd_ptr[1-id] != NULL)//if the other port is working;don't change vbus status
+			return;
+	}
+	if (vbus_otg_en_gpio[id][0] >= 0)
+		gpio_set_value(vbus_otg_en_gpio[id][0], !(on_off^vbus_otg_en_gpio[id][1]));
+}
+
+
+static void aotg_hub_notify_hcd_exit(int state)
+{
+	static int is_first_call = 1;
+
+	if (is_first_call) {
+		is_first_call = 0;
+		aotg_hub_notify_func = (aotg_hub_symbol_func_t)kallsyms_lookup_name("aotg_hub_notify_exit");
+	}
+	if (aotg_hub_notify_func) {
+		aotg_hub_notify_func(state);
+	}
+	return;
+}
+
+static ulong get_fifo_addr(struct aotg_hcd *acthcd, int size)
+{
+	int i, j;
+	ulong addr = 0;
+	int mul = size / ALLOC_FIFO_UNIT;
+	int max_unit = AOTG_MAX_FIFO_SIZE/ALLOC_FIFO_UNIT;
+	int find_next = 0;
+
+	if (mul == 0)
+		mul = 1;
+
+	for (i = 2; i < max_unit;) {
+		if (acthcd->fifo_map[i] != 0) {
+			i++;
+			continue;    //find first unused addr
+		}
+
+		for (j = i; j < max_unit; j++) {
+			if ((j - i + 1) == mul)
+				break;
+
+			if (acthcd->fifo_map[j]) {
+				i = j;
+				find_next = 1;
+				break;
+			}
+		}
+
+		if (j == 64) {
+			break;
+		} else if (find_next) {
+			find_next = 0;
+			continue;
+		} else {
+			int k;
+			for (k = i; k <= j; k++) {
+				acthcd->fifo_map[k] = (1 << 31) | (i * 64);
+			}
+			addr = i * ALLOC_FIFO_UNIT;
+			break;
+		}
+	}
+
+	return addr;
+}
+
+static void release_fifo_addr(struct aotg_hcd *acthcd, ulong addr)
+{
+	int i;
+
+	for (i = addr/ALLOC_FIFO_UNIT; i < AOTG_MAX_FIFO_SIZE/ALLOC_FIFO_UNIT ; i++) {
+		if ((acthcd->fifo_map[i] & 0x7FFFFFFF) == addr)
+			acthcd->fifo_map[i] = 0;
+ 		else
+			break;
+	}
+	return;
+}
+
+static struct aotg_queue * aotg_hcd_get_queue(struct aotg_hcd *acthcd, struct urb *urb, unsigned mem_flags)
+{
+	int i;
+	int empty_idx = -1;
+	struct aotg_queue *q = NULL;
+
+	for (i = 0; i < AOTG_QUEUE_POOL_CNT; i++) {
+		if (acthcd->queue_pool[i] != NULL) {
+			if (acthcd->queue_pool[i]->in_using == 0) {
+				q = acthcd->queue_pool[i];
+				break;
+			}
+		} else {
+			if (empty_idx < 0) {
+				empty_idx = i;
+			}
+		}
+	}
+	if (i == AOTG_QUEUE_POOL_CNT) {
+		q = kzalloc(sizeof(*q), GFP_ATOMIC);
+		if (unlikely(!q)) {
+			dev_err(acthcd->dev, "aotg_hcd_get_queue failed\n");
+			return NULL;
+		}
+		if ((empty_idx >= 0) && (empty_idx < AOTG_QUEUE_POOL_CNT)) {
+			acthcd->queue_pool[empty_idx] = q;
+		}
+	}
+
+	memset(q, 0, sizeof(*q));
+	q->length = 0;
+	q->td.trb_vaddr = NULL;
+	INIT_LIST_HEAD(&q->enqueue_list);
+	INIT_LIST_HEAD(&q->dequeue_list);
+	INIT_LIST_HEAD(&q->finished_list);
+
+	q->in_using = 1;
+	return q;
+}
+
+static void aotg_hcd_release_queue(struct aotg_hcd *acthcd, struct aotg_queue *q)
+{
+	int i;
+
+	if (NULL == q)
+		return;
+
+	q->td.trb_vaddr = NULL;
+
+	/* release all */
+	if (q == NULL) {
+		for (i = 0; i < AOTG_QUEUE_POOL_CNT; i++) {
+			if (acthcd->queue_pool[i] != NULL) {
+				kfree(acthcd->queue_pool[i]);
+				acthcd->queue_pool[i] = NULL;
+			}
+		}
+		return;
+	}
+
+	for (i = 0; i < AOTG_QUEUE_POOL_CNT; i++) {
+		if (acthcd->queue_pool[i] == q) {
+			acthcd->queue_pool[i]->in_using = 0;
+			return;
+		}
+	}
+
+	kfree(q);
+	return;
+}
+
+static __inline__ int is_epfifo_busy(struct aotg_hcep *ep, int is_in)
+{
+	
+	if (is_in) 
+		return(EPCS_BUSY & readb(ep->reg_hcepcs)) == 0;	
+	else 
+		return (EPCS_BUSY & readb(ep->reg_hcepcs)) != 0;
+}
+
+static __inline__ void ep_setup(struct aotg_hcep *ep, u8 type, u8 buftype)
+{
+	ep->buftype = buftype;
+	writeb(type | buftype, ep->reg_hcepcon);
+}
+
+static __inline__ void pio_irq_disable(struct aotg_hcd *acthcd, u8 mask)
+{
+	u8 is_out = mask & USB_HCD_OUT_MASK;
+	u8 ep_num = mask & 0x0f;
+
+	if (is_out) {
+		usb_clearbitsw(1 << ep_num, acthcd->base + HCOUTxIEN0);
+	} else {
+		usb_clearbitsw(1 << ep_num, acthcd->base + HCINxIEN0);
+	}
+	return;
+}
+
+static __inline__ void pio_irq_enable(struct aotg_hcd *acthcd, u8 mask)
+{
+	u8 is_out = mask & USB_HCD_OUT_MASK;
+	u8 ep_num = mask & 0x0f;
+
+	if (is_out) {
+		usb_setbitsw(1 << ep_num, acthcd->base + HCOUTxIEN0);
+	} else {
+		usb_setbitsw(1 << ep_num, acthcd->base + HCINxIEN0);
+	}
+	return;
+}
+
+static __inline__ void pio_irq_clear(struct aotg_hcd *acthcd, u8 mask)
+{
+	u8 is_out = mask & USB_HCD_OUT_MASK;
+	u8 ep_num = mask & 0x0f;
+
+	if (is_out) {
+		writew(1 << ep_num, acthcd->base + HCOUTxIRQ0);
+	}
+	else {
+		writew(1 << ep_num, acthcd->base + HCINxIRQ0);
+	}
+	return;
+}
+
+static __inline__ void ep_enable(struct aotg_hcep *ep)
+{
+	usb_setbitsb(0x80, ep->reg_hcepcon);
+}
+
+static __inline__ void ep_disable(struct aotg_hcep *ep)
+{
+	usb_clearbitsb(0x80, ep->reg_hcepcon);
+}
+
+static __inline__ void aotg_sofirq_on(struct aotg_hcd *acthcd)
+{
+	usb_setbitsb((1 << 1), acthcd->base + USBIEN);
+}
+
+static __inline__ void aotg_sofirq_off(struct aotg_hcd *acthcd)
+{
+	usb_clearbitsb(1 << 1, acthcd->base + USBIEN);
+}
+
+static __inline__ int get_subbuffer_count(u8 buftype)
+{
+	int count = 0;
+
+	switch (buftype) {
+	case EPCON_BUF_SINGLE:
+		count = 1;
+		break;
+	case EPCON_BUF_DOUBLE:
+		count = 2;
+		break;
+	case EPCON_BUF_TRIPLE:
+		count = 3;
+		break;
+	case EPCON_BUF_QUAD:
+		count = 4;
+		break;
+	}
+
+	return count;
+}
+
+static __inline__ void aotg_enable_irq(struct aotg_hcd *acthcd)
+{
+	//usb_setbitsb(USBEIRQ_USBIEN | USBEIRQ_CON_DISCONIEN, acthcd->base + USBEIRQ);
+	writeb(USBEIRQ_USBIEN, acthcd->base + USBEIRQ);
+	usb_setbitsb(USBEIRQ_USBIEN, acthcd->base + USBEIEN);
+	usb_setbitsb(0x1<<2, acthcd->base + OTGIEN);
+//DEBUG
+//	usb_setbitsb(0x1<<4,acthcd->base + USBEIEN);
+	
+	printk("USBEIEN(0x%p): 0x%02X\n", acthcd->base + USBEIEN, readb(acthcd->base + USBEIEN));
+	usb_setbitsb(OTGCTRL_BUSREQ, acthcd->base + OTGCTRL);	
+}
+
+static __inline__ void aotg_disable_irq(struct aotg_hcd *acthcd)
+{
+	//usb_setbitsb(USBEIRQ_USBIEN | USBEIRQ_CON_DISCONIEN, acthcd->base + USBEIRQ);
+	writeb(USBEIRQ_USBIEN, acthcd->base + USBEIRQ);
+	usb_clearbitsb(USBEIRQ_USBIEN, acthcd->base + USBEIEN);
+	usb_clearbitsb(0x1<<2, acthcd->base + OTGIEN);
+	usb_clearbitsb(OTGCTRL_BUSREQ, acthcd->base + OTGCTRL);	
+}
+
+static inline void aotg_config_hub_addr(struct urb *urb, struct aotg_hcep *ep) 
+{
+	if (ep->has_hub) {
+		if (urb->dev->speed == USB_SPEED_HIGH) {
+			writeb(usb_pipedevice(urb->pipe), ep->reg_hcep_dev_addr);
+			writeb(urb->dev->portnum, ep->reg_hcep_port);
+		} else {
+			writeb((0x80 | usb_pipedevice(urb->pipe)), ep->reg_hcep_dev_addr);
+			if (urb->dev->speed == USB_SPEED_LOW) {
+				writeb(0x80 | urb->dev->portnum, ep->reg_hcep_port);
+			} else {
+				writeb(urb->dev->portnum, ep->reg_hcep_port);
+			}
+		}
+		//writeb(0, ep->reg_hcep_splitcs);
+	} else {
+		writeb(usb_pipedevice(urb->pipe), ep->reg_hcep_dev_addr);
+		writeb(urb->dev->portnum, ep->reg_hcep_port);
+	}
+}
+
+#if (1)
+static void aotg_start_ring_transfer(struct aotg_hcd *acthcd, struct aotg_hcep *ep,
+		struct urb *urb)
+{
+	u32 addr;
+	struct aotg_trb *trb;
+	struct aotg_ring *ring = ep->ring;
+
+	aotg_config_hub_addr(urb, ep);
+	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+		writeb(ep->interval, ep->reg_hcep_interval);
+		if (ring->is_out) {
+			trb = ring->dequeue_trb;
+			trb->hw_buf_ptr = urb->transfer_dma;
+			trb->hw_buf_len = urb->transfer_buffer_length;
+		}
+
+	}
+	ep_enable(ep);
+	addr = ring_trb_virt_to_dma(ring, ring->dequeue_trb);
+	aotg_start_ring(ring, addr);
+}
+
+#else
+static void aotg_start_ring_transfer(struct aotg_hcd *acthcd, struct aotg_hcep *ep,
+							struct urb *urb)
+{
+	u32 addr;
+	struct aotg_ring *ring = ep->ring;
+
+	aotg_config_hub_addr(urb, ep);
+	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+		writeb(ep->interval, ep->reg_hcep_interval);
+		addr = ring_trb_virt_to_dma(ring, ring->first_trb);
+	} else {
+		addr = ring_trb_virt_to_dma(ring, ring->dequeue_trb);
+	}
+	ep_enable(ep);	
+	aotg_start_ring(ring, addr);
+}
+#endif
+/*
+static void aotg_stop_ring_transfer(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	struct aotg_ring *ring = ep->ring;
+
+	ep_disable(ep);
+	aotg_stop_ring(ring);
+}
+*/
+static int aotg_hcep_config_iso(struct aotg_hcd *acthcd, struct aotg_hcep *ep,
+			u8 type, u8 buftype, int is_out)
+{
+	int index = 0;
+	ulong addr = 0;
+	int get_ep = 0;
+	int subbuffer_count;
+	//u8 fifo_ctrl;
+
+	if (0 == (subbuffer_count = get_subbuffer_count(buftype))) {
+		dev_err(acthcd->dev, "error buftype: %02X, %s, %d\n", buftype, __func__, __LINE__);
+		return -EPIPE;
+	}
+
+	if (is_out) {
+		for (index = 1; index < MAX_EP_NUM; index++) {
+			if (acthcd->outep[index] == NULL) {
+				ep->is_out = 1;
+				ep->index = index;
+				ep->mask = (u8) (USB_HCD_OUT_MASK | index);
+				acthcd->outep[index] = ep;
+				get_ep = 1;
+				break;
+			}
+		}
+	} else {
+		for (index = 1; index < MAX_EP_NUM; index++) {
+			if (acthcd->inep[index] == NULL) {
+				ep->is_out = 0;
+				ep->index = index;
+				ep->mask = (u8) index;
+				acthcd->inep[index] = ep;
+				get_ep = 1;
+				break;
+			}
+		}
+	}
+
+	if (!get_ep) {
+		dev_err(acthcd->dev, "%s: no more available space for ep\n", __func__);
+		return -ENOSPC;
+	}
+
+	addr = get_fifo_addr(acthcd, subbuffer_count * MAX_PACKET(ep->maxpacket));
+	if (addr == 0) {
+		dev_err(acthcd->dev, "buffer configuration overload!! addr: %08X, subbuffer_count: %d, ep->maxpacket: %u\n",
+				(u32)addr, subbuffer_count, MAX_PACKET(ep->maxpacket));
+		if (is_out) {
+			acthcd->outep[ep->index] = NULL;
+		}
+		else {
+			acthcd->inep[ep->index] = NULL;
+		}
+		return -ENOSPC;
+	}
+	else {
+		ep->fifo_addr = addr;
+	}
+
+	ep->reg_hcepcon = get_hcepcon_reg(is_out, 
+							acthcd->base + HCOUT1CON, 
+							acthcd->base + HCIN1CON, 
+							ep->index);
+	ep->reg_hcepcs = get_hcepcs_reg(is_out, 
+							acthcd->base + HCOUT1CS, 
+							acthcd->base + HCIN1CS, 
+							ep->index);
+	ep->reg_hcepbc = get_hcepbc_reg(is_out, 
+							acthcd->base + HCOUT1BCL, 
+							acthcd->base + HCIN1BCL, 
+							ep->index);
+	ep->reg_hcepctrl = get_hcepctrl_reg(is_out, 
+							acthcd->base + HCOUT1CTRL, 
+							acthcd->base + HCIN1CTRL, 
+							ep->index);
+	ep->reg_hcmaxpck = get_hcepmaxpck_reg(is_out, 
+							acthcd->base + HCOUT1MAXPCKL, 
+							acthcd->base + HCIN1MAXPCKL, 
+							ep->index);
+	ep->reg_hcepaddr = get_hcepaddr_reg(is_out, 
+							acthcd->base + HCOUT1STADDR, 
+	    						acthcd->base + HCIN1STADDR, 
+	    						ep->index);
+	ep->reg_hcep_dev_addr = get_hcep_dev_addr_reg(is_out,
+							acthcd->base + HCOUT1ADDR, 
+	    						acthcd->base + HCIN1ADDR, 
+	    						ep->index);
+	ep->reg_hcep_port = get_hcep_port_reg(is_out,
+							acthcd->base + HCOUT1PORT, 
+	    						acthcd->base + HCIN1PORT, 
+	    						ep->index);
+	ep->reg_hcep_splitcs = get_hcep_splitcs_reg(is_out,
+							acthcd->base + HCOUT1SPILITCS, 
+	    						acthcd->base + HCIN1SPILITCS, 
+	    						ep->index);
+
+	//ep->reg_hcfifo = get_hcfifo_reg(acthcd->base + FIFO1DATA, ep->index);
+	if (!is_out) {
+		///* 5202 is just for write, read's HCINXCOUNT address is not the same with write address. */
+		//ep->reg_hcincount_wt = acthcd->base + HCIN1_COUNTL + (ep->index - 1) * 4;
+		//ep->reg_hcincount_rd = acthcd->base + HCIN1_COUNTL + (ep->index - 1) * 2;
+		ep->reg_hcerr = acthcd->base + HCIN0ERR + ep->index * 0x4;
+		ep->reg_hcep_interval = acthcd->base + HCEP0BINTERVAL + ep->index * 0x8;
+	}
+	else {
+		ep->reg_hcerr = acthcd->base + HCOUT0ERR + ep->index * 0x4;
+		ep->reg_hcep_interval = acthcd->base + HCOUT1BINTERVAL + (ep->index - 1) * 0x8;
+	}
+
+#ifdef DEBUG_EP_CONFIG
+	dev_info(acthcd->dev, "== ep->index: %d, is_out: %d, fifo addr: %08X\n", ep->index, is_out, (u32)addr);
+	dev_info(acthcd->dev, "== reg_hcepcon: %08lX, reg_hcepcs: %08lX, reg_hcepbc: %08lX, reg_hcepctrl: %08lX, reg_hcmaxpck: %08lX, ep->reg_hcepaddr: %08lX\n",
+			ep->reg_hcepcon,
+			ep->reg_hcepcs,
+			ep->reg_hcepbc,
+			ep->reg_hcepctrl,
+			ep->reg_hcmaxpck,
+			ep->reg_hcepaddr);
+#endif
+	
+	/*allocate buffer address of ep fifo */
+	writel(addr, ep->reg_hcepaddr);
+	writew(ep->maxpacket, ep->reg_hcmaxpck);
+	ep_setup(ep, type, buftype);	/*ep setup */
+	
+	/*reset this ep */
+	usb_settoggle(ep->udev, ep->epnum, is_out, 0);
+	aotg_hcep_reset(acthcd, ep->mask, ENDPRST_FIFORST | ENDPRST_TOGRST);
+	writeb(ep->epnum, ep->reg_hcepctrl);
+
+	return 0;
+}
+
+//support 3 bulk, 1 interrupt
+static int aotg_hcep_config(struct aotg_hcd *acthcd,
+			    struct aotg_hcep *ep,
+			    u8 type, u8 buftype, int is_out)
+{
+	int index = 0;
+	ulong addr = 0;
+	int get_ep = 0;
+	int subbuffer_count;
+	//u8 fifo_ctrl;
+
+	if (0 == (subbuffer_count = get_subbuffer_count(buftype))) {
+		dev_err(acthcd->dev, "error buftype: %02X, %s, %d\n", buftype, __func__, __LINE__);
+		return -EPIPE;
+	}
+
+	if (is_out) {
+		for (index = 1; index < MAX_EP_NUM; index++) {
+			if (acthcd->outep[index] == NULL) {
+				ep->is_out = 1;
+				ep->index = index;
+				ep->mask = (u8) (USB_HCD_OUT_MASK | index);
+				acthcd->outep[index] = ep;
+				get_ep = 1;
+				break;
+			}
+		}
+	} else {
+		for (index = 1; index < MAX_EP_NUM; index++) {
+			if (acthcd->inep[index] == NULL) {
+				ep->is_out = 0;
+				ep->index = index;
+				ep->mask = (u8) index;
+				acthcd->inep[index] = ep;
+				get_ep = 1;
+				break;
+			}
+		}
+	}
+
+	if (!get_ep) {
+		dev_err(acthcd->dev, "%s: no more available space for ep\n", __func__);
+		return -ENOSPC;
+	}
+
+	addr = get_fifo_addr(acthcd, subbuffer_count * MAX_PACKET(ep->maxpacket));
+	if (addr == 0) {
+		dev_err(acthcd->dev, "buffer configuration overload!! addr: %08X, subbuffer_count: %d, ep->maxpacket: %u\n",
+				(u32)addr, subbuffer_count, MAX_PACKET(ep->maxpacket));
+		if (is_out) {
+			acthcd->outep[ep->index] = NULL;
+		}
+		else {
+			acthcd->inep[ep->index] = NULL;
+		}
+		return -ENOSPC;
+	}
+	else {
+		ep->fifo_addr = addr;
+	}
+
+	ep->reg_hcepcon = get_hcepcon_reg(is_out, 
+							acthcd->base + HCOUT1CON, 
+							acthcd->base + HCIN1CON, 
+							ep->index);
+	ep->reg_hcepcs = get_hcepcs_reg(is_out, 
+							acthcd->base + HCOUT1CS, 
+							acthcd->base + HCIN1CS, 
+							ep->index);
+	ep->reg_hcepbc = get_hcepbc_reg(is_out, 
+							acthcd->base + HCOUT1BCL, 
+							acthcd->base + HCIN1BCL, 
+							ep->index);
+	ep->reg_hcepctrl = get_hcepctrl_reg(is_out, 
+							acthcd->base + HCOUT1CTRL, 
+							acthcd->base + HCIN1CTRL, 
+							ep->index);
+	ep->reg_hcmaxpck = get_hcepmaxpck_reg(is_out, 
+							acthcd->base + HCOUT1MAXPCKL, 
+							acthcd->base + HCIN1MAXPCKL, 
+							ep->index);
+	ep->reg_hcepaddr = get_hcepaddr_reg(is_out, 
+							acthcd->base + HCOUT1STADDR, 
+	    						acthcd->base + HCIN1STADDR, 
+	    						ep->index);
+	ep->reg_hcep_dev_addr = get_hcep_dev_addr_reg(is_out,
+							acthcd->base + HCOUT1ADDR, 
+	    						acthcd->base + HCIN1ADDR, 
+	    						ep->index);
+	ep->reg_hcep_port = get_hcep_port_reg(is_out,
+							acthcd->base + HCOUT1PORT, 
+	    						acthcd->base + HCIN1PORT, 
+	    						ep->index);
+	ep->reg_hcep_splitcs = get_hcep_splitcs_reg(is_out,
+							acthcd->base + HCOUT1SPILITCS, 
+	    						acthcd->base + HCIN1SPILITCS, 
+	    						ep->index);
+
+	//ep->reg_hcfifo = get_hcfifo_reg(acthcd->base + FIFO1DATA, ep->index);
+	if (!is_out) {
+		///* 5202 is just for write, read's HCINXCOUNT address is not the same with write address. */
+		//ep->reg_hcincount_wt = acthcd->base + HCIN1_COUNTL + (ep->index - 1) * 4;
+		//ep->reg_hcincount_rd = acthcd->base + HCIN1_COUNTL + (ep->index - 1) * 2;
+		ep->reg_hcerr = acthcd->base + HCIN0ERR + ep->index * 0x4;
+		ep->reg_hcep_interval = acthcd->base + HCEP0BINTERVAL + ep->index * 0x8;
+	}
+	else {
+		ep->reg_hcerr = acthcd->base + HCOUT0ERR + ep->index * 0x4;
+		ep->reg_hcep_interval = acthcd->base + HCOUT1BINTERVAL + (ep->index - 1) * 0x8;
+	}
+
+#ifdef DEBUG_EP_CONFIG
+	dev_info(acthcd->dev, "== ep->index: %d, is_out: %d, fifo addr: %08X\n", ep->index, is_out, (u32)addr);
+	dev_info(acthcd->dev, "== reg_hcepcon: %08lX, reg_hcepcs: %08lX, reg_hcepbc: %08lX, reg_hcepctrl: %08lX, reg_hcmaxpck: %08lX, ep->reg_hcepaddr: %08lX\n",
+			ep->reg_hcepcon,
+			ep->reg_hcepcs,
+			ep->reg_hcepbc,
+			ep->reg_hcepctrl,
+			ep->reg_hcmaxpck,
+			ep->reg_hcepaddr);
+#endif
+	
+	pio_irq_disable(acthcd, ep->mask);
+	pio_irq_clear(acthcd, ep->mask);
+	
+	ep_disable(ep);
+
+	/*allocate buffer address of ep fifo */
+	writel(addr, ep->reg_hcepaddr);
+	writew(ep->maxpacket, ep->reg_hcmaxpck);
+	ep_setup(ep, type, buftype);	/*ep setup */
+	
+	/*reset this ep */
+	usb_settoggle(ep->udev, ep->epnum, is_out, 0);
+	aotg_hcep_reset(acthcd, ep->mask, ENDPRST_FIFORST | ENDPRST_TOGRST);
+	writeb(ep->epnum, ep->reg_hcepctrl);
+
+	//fifo_ctrl = (1<<5) | ((!!is_out) << 4) | ep->index; //set auto fifo
+	//writeb(fifo_ctrl, acthcd->base + FIFOCTRL);
+	//pio_irq_enable(acthcd, ep->mask);
+
+	return 0;
+}
+
+static int aotg_hcep_set_split_micro_frame(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	static const u8 split_val[] = {0x31, 0x42, 0x53, 0x64, 0x75, 0x17, 0x20};
+	int i, index;
+	u8 set_val, rd_val;
+
+	for (i=0; i<sizeof(split_val); i++) {
+		set_val = split_val[i];
+
+		for (index=0; index<MAX_EP_NUM; index++) {
+			if (acthcd->inep[index] != NULL) {
+				rd_val = acthcd->inep[index]->reg_hcep_splitcs_val;
+
+				if ((0 == rd_val) || (set_val != rd_val)) {
+					continue;
+				}
+				if (set_val == rd_val)
+					set_val = 0;
+				break;
+			}
+		}
+		if (set_val == 0)
+			continue;
+
+		for (index=0; index<MAX_EP_NUM; index++) {
+			if (acthcd->outep[index] != NULL) {
+				rd_val = acthcd->outep[index]->reg_hcep_splitcs_val;
+
+				if ((0 == rd_val) || (set_val != rd_val)) {
+					continue;
+				}
+				if (set_val == rd_val)
+					set_val = 0;
+				break;
+			}
+		}
+
+		if (set_val != 0)
+			break;
+	}
+
+	if (set_val != 0) {
+		ep->reg_hcep_splitcs_val = set_val;
+		writeb(set_val, ep->reg_hcep_splitcs);
+		printk("====reg_hcep_splitcs_val:%x, index:%d\n", set_val, ep->index);
+	}
+	return 0;
+}
+
+static void finish_request(struct aotg_hcd *acthcd,
+			   struct aotg_queue *q,
+			   int status)
+{
+	struct urb *urb = q->urb;
+
+	if (unlikely((acthcd == NULL) || (q == NULL) || (urb == NULL))) {
+		WARN_ON(1);
+		return;
+	}
+
+	q->status = status;
+	if (list_empty(&q->finished_list)) {
+		list_add_tail(&q->finished_list, &acthcd->hcd_finished_list);
+	} else {
+		ACT_HCD_ERR
+	}
+	tasklet_hi_schedule(&acthcd->urb_tasklet);
+	return;
+}
+
+static void tasklet_finish_request(struct aotg_hcd *acthcd,
+			   struct aotg_queue *q,
+			   int status)
+{
+	struct urb *urb = q->urb;
+	struct aotg_hcep *ep = q->ep;
+
+	if (unlikely((acthcd == NULL) || (q == NULL) || (urb == NULL))) {
+		WARN_ON(1);
+		return;
+	}
+
+	if ((q != NULL) && (ep != NULL)) {
+		if (ep->q == NULL) {
+			ACT_HCD_ERR
+		} else {
+			if (ep->q == q) {
+				ep->q = NULL;
+			}
+		}
+	} else {
+		ACT_HCD_ERR
+		return;
+	}
+
+	if (status == 0) {
+		q->err_count = 0;
+	}
+
+	if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
+		if ((acthcd->active_ep0 != NULL) && (acthcd->active_ep0 == q->ep)) {
+			if (acthcd->active_ep0->q == NULL) {
+				acthcd->active_ep0 = NULL;
+			} else {
+				ACT_HCD_ERR
+			}
+		} else {
+			ACT_HCD_ERR
+		}
+	} 
+#if 0
+	if (q->td.trb_vaddr && q->td.trb_num) {
+		dma_free_coherent(aotg_to_hcd(acthcd)->self.controller,
+			q->td.trb_num * sizeof(struct aotg_trb),
+			q->td.trb_vaddr, q->td.trb_dma);
+	}
+#endif
+	aotg_dbg_finish_q(q);
+	aotg_hcd_release_queue(acthcd, q);
+	//usb_hcd_unlink_urb_from_ep(hcd, urb);
+	//usb_hcd_giveback_urb(hcd, urb, status);
+
+	ep->urb_endque_cnt++;
+	//ep->fifo_busy = 0;
+	//if (usb_pipeint(urb->pipe)) 
+	return;
+}
+
+static __inline__ void handle_status(struct aotg_hcd *acthcd, struct aotg_hcep *ep, int is_out)
+{
+	/*status always DATA1,set 1 to ep0 toggle */
+	writeb(EP0CS_HCSETTOOGLE, acthcd->base + EP0CS);
+
+	if (is_out) {
+		writeb(0, acthcd->base + HCIN0BC); //recv 0 packet
+	}
+	else {
+		writeb(0, acthcd->base + HCOUT0BC); //send 0 packet
+	}
+}
+
+static void write_hcep0_fifo(struct aotg_hcd *acthcd, struct aotg_hcep *ep, struct urb *urb)
+{
+	u32 *buf;
+	int length, count;
+	void __iomem *addr = acthcd->base + EP0INDATA_W0;
+
+	if (!(readb(acthcd->base + EP0CS) & EP0CS_HCOUTBSY)) {
+		buf = (u32 *) (urb->transfer_buffer + urb->actual_length);
+		prefetch(buf);
+
+		/* how big will this packet be? */
+		length = min((int)ep->maxpacket, (int)urb->transfer_buffer_length - (int)urb->actual_length);
+
+		count = length >> 2;	/*wirte in DWORD */
+		if (length & 0x3) count++;
+
+		while (likely(count--)) {
+			writel(*buf, addr);
+			buf++;
+			addr += 4;
+		}
+
+		ep->length = length;
+		writeb(length, acthcd->base + HCOUT0BC);
+		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), 1);
+	} else {
+		dev_err(acthcd->dev, "<CTRL>OUT data is not ready\n");
+	}
+}
+
+static void read_hcep0_fifo(struct aotg_hcd *acthcd, struct aotg_hcep *ep, struct urb *urb)
+{
+	u8 *buf;
+	unsigned overflag, is_short, shorterr, is_last;
+	unsigned length, count;
+	struct usb_device *udev;
+	void __iomem *addr = acthcd->base + EP0OUTDATA_W0;  //HCEP0INDAT0;
+	unsigned bufferspace;
+
+	overflag = 0;
+	is_short = 0;
+	shorterr = 0;
+	is_last = 0;
+	udev = ep->udev;
+
+	if (readb(acthcd->base + EP0CS) & EP0CS_HCINBSY) {
+		dev_err(acthcd->dev, "<CTRL>IN data is not ready\n");
+		return;
+	} else {
+		usb_dotoggle(udev, ep->epnum, 0);
+		buf = urb->transfer_buffer + urb->actual_length;
+		bufferspace = urb->transfer_buffer_length - urb->actual_length;
+		//prefetch(buf);
+
+		length = count = readb(acthcd->base + HCIN0BC);
+		if (length > bufferspace) {
+			count = bufferspace;
+			urb->status = -EOVERFLOW;
+			overflag = 1;
+		}
+
+		urb->actual_length += count;
+		while (count--) {
+			*buf++ = readb(addr);
+#if 0
+			buf--;
+			printk("ep0in:%x, cnt:%d\n", (unsigned int)*buf, count);
+			buf++;
+#endif
+			addr++;
+		}
+
+		if (urb->actual_length >= urb->transfer_buffer_length) {
+			ep->nextpid = USB_PID_ACK;
+			is_last = 1;
+			handle_status(acthcd, ep, 0);
+		} else if (length < ep->maxpacket) {
+			is_short = 1;
+			is_last = 1;
+			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+				urb->status = -EREMOTEIO;
+				shorterr = 1;
+			}
+			ep->nextpid = USB_PID_ACK;
+			handle_status(acthcd, ep, 0);
+		}
+		else {
+			writeb(0, acthcd->base + HCIN0BC);
+		}
+	}
+}
+
+static int handle_setup_packet(struct aotg_hcd *acthcd, struct aotg_queue *q)
+{
+	struct urb *urb = q->urb;
+	struct aotg_hcep *ep = q->ep;
+	u32 *buf;
+	void __iomem *addr = acthcd->base + EP0INDATA_W0;
+	int i = 0;
+
+#ifdef DEBUG_SETUP_DATA
+	u16 w_value, w_index, w_length;
+	struct usb_ctrlrequest *ctrlreq;
+
+	ctrlreq = (struct usb_ctrlrequest *)urb->setup_packet;
+	w_value = le16_to_cpu(ctrlreq->wValue);
+	w_index = le16_to_cpu(ctrlreq->wIndex);
+	w_length = le16_to_cpu(ctrlreq->wLength);
+	dev_info(acthcd->dev, "<CTRL>SETUP stage  %02x.%02x V%04x I%04x L%04x\n ",
+		  ctrlreq->bRequestType, ctrlreq->bRequest, w_value, w_index,
+		  w_length);
+#endif
+	if ((q->is_xfer_start) || (ep->q)) {
+		ACT_HCD_DBG
+		printk("q->is_xfer_start:%d\n", q->is_xfer_start);
+		return 0;
+	}
+	if (unlikely(!HC_IS_RUNNING(aotg_to_hcd(acthcd)->state))) {
+		ACT_HCD_DBG
+		return -ESHUTDOWN;
+	}
+	if (acthcd->active_ep0 != NULL) {
+		ACT_HCD_ERR
+		return -EBUSY;
+	}
+
+	writeb(ep->epnum, acthcd->base + HCEP0CTRL);
+	writeb((u8)ep->maxpacket, acthcd->base + HCIN0MAXPCK);
+
+	acthcd->active_ep0 = ep;
+	ep->q = q;
+	q->is_xfer_start = 1;
+	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 1, 1);
+	ep->nextpid = USB_PID_SETUP;
+	buf = (u32 *) urb->setup_packet;
+
+	/*initialize the setup stage */
+	writeb(EP0CS_HCSET, acthcd->base + EP0CS);
+	while (readb(acthcd->base + EP0CS) & EP0CS_HCOUTBSY) {
+		writeb(EP0CS_HCSET, acthcd->base + EP0CS);
+		i++;
+		if (i > 2000000) {
+			printk("handle_setup timeout!\n");
+			break;
+		}
+	}
+	
+	if (!(readb(acthcd->base + EP0CS) & EP0CS_HCOUTBSY)) {
+		/*fill the setup data in fifo */
+		writel(*buf, addr);
+		addr += 4;
+		buf++;
+		writel(*buf, addr);
+		writeb(8, acthcd->base + HCOUT0BC);
+	}
+	else {
+		dev_warn(acthcd->dev, "setup ep busy!!!!!!!\n");
+	}
+
+	return 0;
+}
+
+static void handle_hcep0_out(struct aotg_hcd *acthcd)
+{
+	struct aotg_hcep *ep;
+	struct urb *urb;
+	struct usb_device *udev;
+	struct aotg_queue *q;
+	
+	ep = acthcd->active_ep0;
+	
+	if (unlikely(!ep)) {
+		ACT_HCD_ERR
+		return;
+	}
+	q = ep->q;
+	if (q == NULL) {
+		ACT_HCD_ERR
+		return;
+	}
+
+	urb = q->urb;
+	udev = ep->udev;
+
+	switch (ep->nextpid) {
+	case USB_PID_SETUP:
+		if (urb->transfer_buffer_length == urb->actual_length) {
+			ep->nextpid = USB_PID_ACK;
+			handle_status(acthcd, ep, 1);	/*no-data transfer */
+		} else if (usb_pipeout(urb->pipe)) {
+			usb_settoggle(udev, 0, 1, 1);
+			ep->nextpid = USB_PID_OUT;
+			write_hcep0_fifo(acthcd, ep, urb);
+		} else {
+			usb_settoggle(udev, 0, 0, 1);
+			ep->nextpid = USB_PID_IN;
+			writeb(0, acthcd->base + HCIN0BC);
+		}
+		break;
+	case USB_PID_OUT:
+		urb->actual_length += ep->length;
+		usb_dotoggle(udev, ep->epnum, 1);
+		if (urb->actual_length >= urb->transfer_buffer_length) {
+			ep->nextpid = USB_PID_ACK;
+			handle_status(acthcd, ep, 1);	/*control write transfer */
+		}
+		else {
+			ep->nextpid = USB_PID_OUT;
+			write_hcep0_fifo(acthcd, ep, urb);
+		}
+		break;
+	case USB_PID_ACK:
+		finish_request(acthcd, q, 0);
+		break;
+	default:
+		dev_err(acthcd->dev, "<CTRL>ep0 out ,odd pid %d, %s, %d\n", 
+				ep->nextpid, __func__, __LINE__);
+	}
+}
+
+static void handle_hcep0_in(struct aotg_hcd *acthcd)
+{
+	struct aotg_hcep *ep;
+	struct urb *urb;
+	struct usb_device *udev;
+	struct aotg_queue *q;
+	
+	ep = acthcd->active_ep0;
+	if (unlikely(!ep)) {
+		return;
+	}
+	q = ep->q;
+	if (q == NULL) {
+		ACT_HCD_ERR
+		return;
+	}
+
+	urb = q->urb;
+	udev = ep->udev;
+
+	switch (ep->nextpid) {
+	case USB_PID_IN:
+		read_hcep0_fifo(acthcd, ep, urb);
+		break;
+	case USB_PID_ACK:
+		finish_request(acthcd, q, 0);
+		break;
+	default:
+		dev_err(acthcd->dev, "<CTRL>ep0 out ,odd pid %d\n", ep->nextpid);
+	}
+}
+
+static void aotg_hcd_err_handle(struct aotg_hcd *acthcd, u32 irqvector, 
+				int ep_num, int is_in)
+{
+	struct urb *urb;
+	struct aotg_queue *q;
+	struct aotg_hcep *ep = NULL;
+	struct aotg_ring *ring = NULL;
+	struct aotg_td *td = NULL;
+	int status = -EOVERFLOW;
+	u8 err_val = 0;
+	u8 err_type = 0;
+	u8 reset = 0;
+	struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+
+	printk("hcd ep err ep_num:%d, is_in:%d\n", ep_num, is_in);
+		
+	if (ep_num == 0) {
+		ep = acthcd->active_ep0;
+		if (ep == NULL) {
+			ACT_HCD_ERR
+			return;
+		}
+		q = ep->q;
+		if (is_in) {
+			ep->reg_hcerr = acthcd->base + HCIN0ERR;
+		} else {
+			ep->reg_hcerr = acthcd->base + HCOUT0ERR;
+		}
+	} else {
+		if (is_in) {
+			ep = acthcd->inep[ep_num];
+		} else {
+			ep = acthcd->outep[ep_num];
+		}
+		if (ep == NULL) {
+			ACT_HCD_ERR
+			printk("is_in:%d, ep_num:%d\n", is_in, ep_num);
+			return;
+		}
+		ring = ep->ring;
+		if (!ring) {
+			ACT_HCD_ERR
+			return;
+		}
+		td = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+		if (!td) {
+			aotg_stop_ring(ring);
+			ACT_HCD_ERR
+			return;
+		}
+	}
+	
+	err_val = readb(ep->reg_hcerr);
+	if (is_in) {
+		writew(1 << ep_num, acthcd->base + HCINxERRIRQ0);
+	} else {
+		writew(1 << ep_num, acthcd->base + HCOUTxERRIRQ0);
+	}
+
+	err_type = err_val & HCINxERR_TYPE_MASK;
+	printk("err_type:%x\n",err_type>>2);
+	switch (err_type) {
+	case HCINxERR_NO_ERR:
+	case HCINxERR_OVER_RUN:
+		status = -EOVERFLOW;
+		break;
+	case HCINxERR_UNDER_RUN:
+		status = -EREMOTEIO;
+		break;
+	case HCINxERR_STALL:
+		status = -EPIPE;
+		break;
+	case HCINxERR_TIMEOUT:
+		status = -ETIMEDOUT;
+		break;
+	case HCINxERR_CRC_ERR:
+	case HCINxERR_TOG_ERR:
+	case HCINxERR_PID_ERR:
+		status = -EPROTO;
+		break;
+	//case HCINxERR_SPLIET:
+	default:
+		printk("err_val:0x%x, err_type:%d\n", err_val, err_type);
+		if (is_in) {
+			printk("HCINEP%dSPILITCS:0x%x\n", ep_num, 
+					readb(acthcd->base + ep_num * 8 + HCEP0SPILITCS));
+		} else { 
+			printk("HCOUTEP%dSPILITCS:0x%x\n", ep_num, 
+					readb(acthcd->base + (ep_num - 1) * 8 + HCOUT1SPILITCS));
+		}
+		status = -EPIPE;
+		break;
+
+	//default:
+	//	printk("err_type:%x\n", err_type);
+	//	status = -EOVERFLOW;
+	//	reset = ENDPRST_FIFORST | ENDPRST_TOGRST;
+	}
+
+	if (!(acthcd->port & USB_PORT_STAT_ENABLE)
+			|| (acthcd->port & (USB_PORT_STAT_C_CONNECTION << 16))
+			|| (acthcd->hcd_exiting != 0)
+			|| (acthcd->inserted == 0)
+    		|| !HC_IS_RUNNING(hcd->state)) {
+		dev_err(acthcd->dev, "usbport, dead, port:%x, hcd_exiting:%d \n", acthcd->port, acthcd->hcd_exiting);
+		status = -ENODEV;
+	}
+
+	if (ep->index == 0) {
+		q = ep->q;
+		urb = q->urb;
+		if ((status == -EPIPE) || (status == -ENODEV)) 
+			writeb(HCINxERR_RESEND, ep->reg_hcerr);  /* resend. */
+		finish_request(acthcd, q, status);
+		dev_info(acthcd->dev, "%s ep %d error [0x%02X] error type [0x%02X], reset it...\n",
+			    usb_pipeout(urb->pipe)?"HC OUT":"HC IN", ep->index, err_val, (err_val>>2)&0x7);
+	} else {
+		if ((status != -EPIPE) && (status != -ENODEV)) {
+			printk("td->err_count:%d\n", td->err_count);
+			td->err_count++;
+			
+			if (td->err_count < MAX_ERROR_COUNT) {				
+				writeb(HCINxERR_RESEND, ep->reg_hcerr);  /* resend. */
+				return;
+			}		
+		}
+			if (status == -ETIMEDOUT || status == -EPIPE) {
+					ep->error_count++;
+		}
+		
+		reset = ENDPRST_FIFORST | ENDPRST_TOGRST;
+		ep_disable(ep);
+		if (is_in) {
+			aotg_hcep_reset(acthcd, ep->mask, reset);
+		} else {
+			aotg_hcep_reset(acthcd, ep->mask | USB_HCD_OUT_MASK, reset);
+		}
+		
+		/*if (usb_pipeout(urb->pipe)) {
+			aotg_hcep_reset(acthcd, ep->mask | USB_HCD_OUT_MASK, reset);
+		} else {
+			aotg_hcep_reset(acthcd, ep->mask, reset);
+		}*/
+		
+		aotg_stop_ring(ring);
+		urb = td->urb;
+		//writel(DMACTRL_DMACC,ep->ring->reg_dmactrl);
+		if (ep->type == PIPE_INTERRUPT)
+			dequeue_intr_td(ring, td);
+		else
+			dequeue_td(ring, td, TD_IN_FINISH);
+		
+		if (urb) {
+			usb_hcd_unlink_urb_from_ep(hcd, urb);
+			usb_hcd_giveback_urb(hcd, urb, status);
+		}
+		else
+		{
+			ERR("urb not exist!\n");
+		}
+
+		/*
+		 * after, need to rewrite port_num, dev_addr when using hub ?
+		 */
+		/*if ((urb) && (!list_empty(&ep->enring_td_list)) &&
+				!is_ring_running(ring)) {
+			ACT_HCD_DBG
+			ep_enable(ep);	
+			addr = ring_trb_virt_to_dma(ring, ring->dequeue_trb);
+			aotg_start_ring(ring, addr);
+		}*/
+		dev_info(acthcd->dev, "%s ep %d error [0x%02X] error type [0x%02X], reset it...\n",
+			    is_in?"HC IN":"HC OUT", ep->index, err_val, (err_val>>2)&0x7);
+	}
+	
+	return;
+}
+#if 0
+static void aotg_hcd_error(struct aotg_hcd *acthcd, u32 irqvector, int ep_num, int is_in)
+{
+	struct aotg_queue *q;
+	struct aotg_hcep *ep = NULL;
+	struct urb *urb;
+	int status;
+	u8 error = 0;
+	u8 reset = 0;
+	struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+
+	printk("hcd ep err ep_num:%d, is_in:%d\n", ep_num, is_in);
+
+	if (ep_num == 0) {
+		ep = acthcd->active_ep0;
+		if (ep == NULL) {
+			ACT_HCD_ERR
+			return;
+		}
+		q = ep->q;
+		if (is_in) {
+			ep->reg_hcerr = acthcd->base + HCIN0ERR;
+		} else {
+			ep->reg_hcerr = acthcd->base + HCOUT0ERR;
+		}
+	} else {
+		if (is_in) {
+			ep = acthcd->inep[ep_num];
+		} else {
+			ep = acthcd->outep[ep_num];
+		}
+		if (ep == NULL) {
+			ACT_HCD_ERR
+			printk("is_in:%d, ep_num:%d\n", is_in, ep_num);
+			return;
+		}
+		q = ep->q;
+	}
+
+	if (is_in) {
+		writew(1 << ep_num, acthcd->base + HCINxERRIRQ0);
+	} else {
+		writew(1 << ep_num, acthcd->base + HCOUTxERRIRQ0);
+	}
+	error = readb(ep->reg_hcerr);
+
+	if (q) {
+		urb = q->urb;
+
+		switch (error & HCINxERR_TYPE_MASK) {
+		case HCINxERR_NO_ERR:
+			status = 0;
+			break;
+		
+		case HCINxERR_STALL:
+			status = -EPIPE;
+			reset = ENDPRST_FIFORST | ENDPRST_TOGRST;
+			break;
+		
+		case HCINxERR_TIMEOUT:
+			status = -ETIMEDOUT;
+			reset = ENDPRST_FIFORST | ENDPRST_TOGRST;
+			break;
+
+		default:
+			printk("error:%x\n", ((error & HCINxERR_TYPE_MASK) >> 2));
+			status = -EIO;
+			reset = ENDPRST_FIFORST | ENDPRST_TOGRST;
+		}
+
+		if (!(acthcd->port & USB_PORT_STAT_ENABLE)
+			|| (acthcd->port & (USB_PORT_STAT_C_CONNECTION << 16))
+			|| (acthcd->hcd_exiting != 0)
+			|| (acthcd->inserted == 0)
+	    		|| !HC_IS_RUNNING(hcd->state)) {
+			dev_err(acthcd->dev, "usbport, dead, port:%x, hcd_exiting:%d \n", acthcd->port, acthcd->hcd_exiting);
+			status = -ENODEV;
+		}
+
+		if (status < 0) {
+			ACT_HCD_DBG
+			printk("status:%d\n", status);
+
+			if (ep->index > 0 && (status != -EPIPE) && (status != -ENODEV)) {
+				printk("q->err_count:%d\n", q->err_count);
+				q->err_count++;
+				writeb(HCINxERR_RESEND, ep->reg_hcerr);  /* resend. */
+
+				if ((q->err_count % MAX_ERROR_COUNT) < (MAX_ERROR_COUNT - 1)) {
+					return;
+				}
+				if (q->err_count > MAX_ERROR_COUNT * 3) {
+					ACT_HCD_DBG
+					q->err_count = 0;
+					acthcd->discon_happened = 1;
+					mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(1));
+					return;
+				}
+			}
+
+			if ((ep->index == 0) && ((status == -EPIPE) || (status == -ENODEV))) {
+				writeb(HCINxERR_RESEND, ep->reg_hcerr);  /* resend. */
+			}
+
+			if (ep->index > 0) {
+				if (usb_pipeout(urb->pipe)) {
+					aotg_hcep_reset(acthcd, ep->mask | USB_HCD_OUT_MASK, reset);
+				} else {
+					ep_disable(ep);
+					aotg_hcep_reset(acthcd, ep->mask, reset);
+				}
+			}
+			dev_info(acthcd->dev, "%s ep %d error [0x%02X] error type [0x%02X], reset it...\n",
+				    usb_pipeout(urb->pipe)?"HC OUT":"HC IN", ep->index, error, (error>>2)&0x7);
+#if 0
+			if (AOTG_GET_DMA_NUM(q->dma_no)) {
+				ACT_HCD_DBG
+				__clear_dma(acthcd, q);
+			}
+#endif
+			finish_request(acthcd, q, status);
+		}
+	}
+	tasklet_hi_schedule(&acthcd->urb_tasklet);
+
+	return;
+}
+#endif 
+
+void aotg_hcd_abort_urb(struct aotg_hcd *acthcd)
+{
+	int cnt;
+	struct aotg_hcep *ep;
+	struct urb *urb;
+	struct aotg_ring *ring;
+	struct aotg_td *td;
+	unsigned long flags;
+//	struct aotg_queue *q;
+	struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+	
+/*	if (HC_IS_SUSPENDED(hcd->state)) {
+		usb_hcd_resume_root_hub(hcd);
+	}
+		//ACT_HCD_DBG
+		//aotg_hcd_flush_queue(acthcd);
+	usb_hcd_poll_rh_status(hcd);*/
+	
+	spin_lock_irqsave(&acthcd->lock, flags);
+	/*ep = acthcd->active_ep0;
+	if (ep && ep->q) {
+		q = ep->q;
+		urb = q->urb;
+		q->status = -ENODEV;
+		//printk("%s in ep 0\n",__func__);
+		aotg_hcd_release_queue(acthcd, q);
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
+		spin_unlock(&acthcd->lock);
+		usb_hcd_giveback_urb(hcd, urb, -ENODEV);
+		spin_lock(&acthcd->lock);
+	}*/
+	
+	for (cnt=1; cnt<MAX_EP_NUM; cnt++) {
+		ep = acthcd->inep[cnt];
+		if (ep) {
+			ring = ep->ring;
+			td = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+			if (!td)
+				continue;
+			urb = td->urb;
+			if (!urb)
+				continue;
+			if (ep->type == PIPE_INTERRUPT)
+				dequeue_intr_td(ring, td);
+			else
+				dequeue_td(ring, td, TD_IN_FINISH);
+			//printk("%s in ep %d\n",__func__,cnt);
+			usb_hcd_unlink_urb_from_ep(hcd, urb);
+			spin_unlock(&acthcd->lock);
+			usb_hcd_giveback_urb(hcd, urb, -ENODEV);
+			spin_lock(&acthcd->lock);
+		}
+	}
+	
+	for (cnt=1; cnt<MAX_EP_NUM; cnt++) {
+		ep = acthcd->outep[cnt];
+		if (ep) {
+			ring = ep->ring;
+			td = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+			if (!td)
+				continue;
+			urb = td->urb;
+			if (!urb)
+				continue;
+			if (ep->type == PIPE_INTERRUPT)
+				dequeue_intr_td(ring, td);
+			else
+				dequeue_td(ring, td, TD_IN_FINISH);
+			//printk("%s out ep %d\n",__func__,cnt);
+			usb_hcd_unlink_urb_from_ep(hcd, urb);
+			spin_unlock(&acthcd->lock);
+			usb_hcd_giveback_urb(hcd, urb, -ENODEV);
+			spin_lock(&acthcd->lock);
+		}
+	}
+	
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+}
+
+static irqreturn_t aotg_hub_irq(struct usb_hcd *hcd)
+{
+	struct platform_device *pdev;
+	unsigned int port_no;
+	u32 irqvector;
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	u8 eirq_mask = readb(acthcd->base + USBEIEN);
+	u8 eirq_pending = readb(acthcd->base + USBEIRQ);
+	u8 otg_state;
+
+	/* take cate to use lock, because in irq -> dma_handler -> finish_request -> 
+	 * usb_hcd_giveback_urb -> urb->complete(), it maybe call enqueue and get spin_lock again.
+	 */
+	//spin_lock(&acthcd->lock);
+	pdev = to_platform_device(hcd->self.controller);
+	port_no = pdev->id & 0xff;
+#if(0)
+	int i = 0;
+	irqvector = (u32)readb(acthcd->base + IVECT);
+	printk("USBEIEN:0x%x, USBEIRQ:0x%x, ivec:0x%x\n", readb(acthcd->base + USBEIEN),
+			readb(acthcd->base + USBEIRQ), irqvector);
+	printk("HCINxDMAIRQ0:0x%x, HCOUTxDMAIRQ0:0x%x\n",
+		readw(acthcd->base + HCINxDMAIRQ0),
+		readw(acthcd->base + HCOUTxDMAIRQ0));
+	for (i = 0; i <= 0x1d; i++) {
+		printk("0x%p : 0x%x\n", acthcd->base + 0x500 + i,
+			readb(acthcd->base + 0x500 + i));
+	}
+#endif
+
+	if (eirq_pending & USBEIRQ_USBIRQ) {
+		irqvector = (u32)readb(acthcd->base + IVECT);
+		writeb(eirq_mask | USBEIRQ_USBIRQ, acthcd->base + USBEIRQ);
+//		HUB_DEBUG("irqvector:%d, 0x%x\n", irqvector, irqvector);
+
+		switch (irqvector) {
+		//case UIV_OTGIRQ:
+		case UIV_IDLE:
+		case UIV_SRPDET:
+		case UIV_LOCSOF:
+		case UIV_VBUSERR:
+		case UIV_PERIPH:
+			if (readb(acthcd->base + OTGIRQ) & (0x1<<2)) {
+				writeb(0x1<<2, acthcd->base + OTGIRQ);
+				otg_state = readb(acthcd->base + OTGSTATE);
+
+				printk("port_no:%d OTG IRQ, OTGSTATE: 0x%02X, USBIRQ:0x%02X\n", 
+					port_no, otg_state,
+					readb(acthcd->base + USBIRQ));
+
+				if (otg_state == 0x4) {
+					return IRQ_HANDLED;
+				}
+				
+				if ((otg_state == 0x02) && port_host_plug_detect[acthcd->id]) {
+					aotg_disable_irq(acthcd);
+					acthcd->hcd_exiting = 1;
+					aotg_hcd_abort_urb(acthcd);
+					aotg_dev_plugout_msg(acthcd->id);
+					return IRQ_HANDLED;
+				}
+				acthcd->put_aout_msg = 0;
+				if (otg_state == AOTG_STATE_A_HOST) {
+					/*if (acthcd->inserted != 0) {
+						acthcd->discon_happened = 1;
+					}*/
+
+					//if (acthcd->port & (USB_PORT_STAT_C_CONNECTION << 16)) {
+					//	mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(1000));
+					//} else {
+						if (acthcd->discon_happened == 1) {
+							mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(500));
+						} else {
+							mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(1));
+						}
+					//}
+				} else {
+					acthcd->discon_happened = 1;
+					mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(1));
+				}
+			} else {
+				printk("port_no:%d error OTG irq! OTGIRQ: 0x%02X\n", 
+					port_no, readb(acthcd->base + OTGIRQ));
+			}
+			break;
+		case UIV_SOF:
+			writeb(USBIRQ_SOF, acthcd->base + USBIRQ);
+#if 0
+			{
+				u16 index;
+				struct aotg_hcep *ep;
+	
+				index = acthcd->frame;
+				ep = acthcd->periodic[index];
+				aotg_hcd_period_transfer(acthcd, ep);
+	
+				acthcd->frame++;
+				acthcd->frame = acthcd->frame % PERIODIC_SIZE;
+			}
+#endif
+			break;
+		case UIV_USBRESET:
+			if (acthcd->port & (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)) {
+				acthcd->speed = USB_SPEED_FULL;	/*FS is the default */
+				acthcd->port |= (USB_PORT_STAT_C_RESET << 16);
+				acthcd->port &= ~USB_PORT_STAT_RESET;
+
+				/*clear usb reset irq */
+				writeb(USBIRQ_URES, acthcd->base + USBIRQ); 
+	
+				/*reset all ep-in */
+				aotg_hcep_reset(acthcd, USB_HCD_IN_MASK,
+						ENDPRST_FIFORST | ENDPRST_TOGRST);
+				/*reset all ep-out */
+				aotg_hcep_reset(acthcd, USB_HCD_OUT_MASK,
+						ENDPRST_FIFORST | ENDPRST_TOGRST);
+	
+				acthcd->port |= USB_PORT_STAT_ENABLE;
+				acthcd->rhstate = AOTG_RH_ENABLE;
+				/*now root port is enabled fully */
+				if (readb(acthcd->base + USBCS) & USBCS_HFMODE) {
+					acthcd->speed = USB_SPEED_HIGH;
+					acthcd->port |= USB_PORT_STAT_HIGH_SPEED;
+					writeb(USBIRQ_HS, acthcd->base + USBIRQ);
+					HCD_DEBUG("%s: USB device is  HS\n", __func__);
+				} else if (readb(acthcd->base + USBCS) & USBCS_LSMODE) {
+					acthcd->speed = USB_SPEED_LOW;
+					acthcd->port |= USB_PORT_STAT_LOW_SPEED;
+					HCD_DEBUG("%s: USB device is  LS\n", __func__);
+				} else {
+					acthcd->speed = USB_SPEED_FULL;
+					HCD_DEBUG("%s: USB device is  FS\n", __func__);
+				}
+	
+				/*usb_clearbitsb(USBIEN_URES,USBIEN);*/ /*disable reset irq */
+				/*khu del for must enable USBIEN_URES again*/
+				writew(0xffff, acthcd->base + HCINxERRIRQ0);
+				writew(0xffff, acthcd->base + HCOUTxERRIRQ0);
+
+				writew(0xffff, acthcd->base + HCINxIRQ0);
+				writew(0xffff, acthcd->base + HCOUTxIRQ0);
+	
+				writew(0xffff, acthcd->base + HCINxERRIEN0);
+				writew(0xffff, acthcd->base + HCOUTxERRIEN0);
+	
+				HCD_DEBUG("%s: USB reset end\n", __func__);
+			}
+			break;
+	
+		case UIV_EP0IN:
+			writew(1, acthcd->base + HCOUTxIRQ0);	/*clear hcep0out irq */
+			handle_hcep0_out(acthcd);
+			break;
+		case UIV_EP0OUT:
+			writew(1, acthcd->base + HCINxIRQ0);	/*clear hcep0in irq */
+			handle_hcep0_in(acthcd);
+			break;
+		case UIV_EP1IN:
+			ACT_HCD_DBG
+			writew(1<<1, acthcd->base + HCOUTxIRQ0);	/*clear hcep1out irq */
+			break;
+		case UIV_EP1OUT:
+			ACT_HCD_DBG
+			writeb(1<<1, acthcd->base + HCINxIRQ0);	/*clear hcep1in irq */
+			break;
+		case UIV_EP2IN:
+			ACT_HCD_DBG
+			writew(1<<2, acthcd->base + HCOUTxIRQ0);	/*clear hcep2out irq */
+			break;
+		case UIV_EP2OUT:
+			ACT_HCD_DBG
+			writeb(1<<2, acthcd->base + HCINxIRQ0);	/*clear hcep2in irq */
+			break;
+
+		default:
+			if ((irqvector >= UIV_HCOUT0ERR) && (irqvector <= UIV_HCOUT15ERR)) {
+				printk("irqvector:%d, 0x%x\n", irqvector, irqvector);
+				aotg_hcd_err_handle(acthcd, irqvector, (irqvector - UIV_HCOUT0ERR), 0);
+				break;
+			}
+			if ((irqvector >= UIV_HCIN0ERR) && (irqvector <= UIV_HCIN15ERR)) {				
+				printk("irqvector:%d, 0x%x\n", irqvector, irqvector);
+				aotg_hcd_err_handle(acthcd, irqvector, (irqvector - UIV_HCIN0ERR), 1);
+				break;
+			}
+			dev_err(acthcd->dev, "error interrupt, pls check it! irqvector: 0x%02X\n", (u8)irqvector);
+			//spin_unlock(&acthcd->lock);
+			return IRQ_NONE;
+		}
+	}
+
+	//writeb(readb(acthcd->base + 0x518), acthcd->base + 0x518);
+
+	
+	aotg_clear_all_overflow_irq(acthcd);
+	aotg_clear_all_shortpkt_irq(acthcd);
+	aotg_clear_all_zeropkt_irq(acthcd);
+	aotg_clear_all_hcoutdma_irq(acthcd);
+	aotg_ring_irq_handler(acthcd);
+
+	//ACT_HCD_DBG
+	//spin_unlock(&acthcd->lock);
+	//printk("%s,(0x%p : 0x%x)\n",__FUNCTION__, acthcd->base + HCINxDMAIRQ0,
+	   //readw(acthcd->base + HCINxDMAIRQ0));
+	return IRQ_HANDLED;
+}
+
+static void aotg_hub_hotplug_timer(unsigned long data)
+{
+	struct aotg_hcd *acthcd = (struct aotg_hcd *)data;
+	struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+	struct platform_device *pdev;
+	unsigned int port_no;
+	unsigned long flags;
+	int connect_changed = 0;
+
+	//if ((void *)data == (void *)NULL) 
+	if (unlikely(IS_ERR_OR_NULL((void *)data))) {
+		ACT_HCD_DBG
+		return;
+	}
+	if (acthcd->hcd_exiting != 0) {
+		ACT_HCD_DBG
+		return;
+	}
+
+	//disable_irq_nosync(acthcd->uhc_irq);
+	disable_irq(acthcd->uhc_irq);
+	spin_lock_irqsave(&acthcd->lock, flags);
+
+	if (acthcd->put_aout_msg != 0) {
+		pdev = to_platform_device(hcd->self.controller);
+		port_no = pdev->id & 0xff;
+		ACT_HCD_DBG
+		//update_driver_state(UPDATE_UDEVICE_OUT, port_no);
+		acthcd->put_aout_msg = 0;
+		spin_unlock_irqrestore(&acthcd->lock, flags);
+		enable_irq(acthcd->uhc_irq);
+		aotg_hub_notify_hcd_exit(0);
+		return;
+	}
+	
+	if ((readb(acthcd->base + OTGSTATE) == AOTG_STATE_A_HOST) && (acthcd->discon_happened == 0)) {
+		if (!acthcd->inserted) {
+			acthcd->port |= (USB_PORT_STAT_C_CONNECTION << 16);
+			/*set port status bit,and indicate the present of  a device */
+			acthcd->port |= USB_PORT_STAT_CONNECTION;
+			acthcd->rhstate = AOTG_RH_ATTACHED;
+			acthcd->inserted = 1;
+			connect_changed = 1;
+		}
+	} else {
+		if (acthcd->inserted) {
+			acthcd->port &= ~(USB_PORT_STAT_CONNECTION |
+					  USB_PORT_STAT_ENABLE |
+					  USB_PORT_STAT_LOW_SPEED |
+					  USB_PORT_STAT_HIGH_SPEED | USB_PORT_STAT_SUSPEND);
+			acthcd->port |= (USB_PORT_STAT_C_CONNECTION << 16);
+			acthcd->rhstate = AOTG_RH_NOATTACHED;
+			acthcd->inserted = 0;
+			connect_changed = 1;
+		}
+		if (acthcd->discon_happened == 1) {
+			acthcd->discon_happened = 0;
+
+			if (readb(acthcd->base + OTGSTATE) == AOTG_STATE_A_HOST) {
+				mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(1000));
+			}
+		}
+	}
+
+	dev_info(acthcd->dev, "<USB> %s connection changed: %d, acthcd->inserted: %d\n", 
+			dev_name(hcd->self.controller), connect_changed, acthcd->inserted);
+	if (connect_changed) {
+		if (HC_IS_SUSPENDED(hcd->state)) {
+			usb_hcd_resume_root_hub(hcd);
+		}
+		ACT_HCD_DBG
+		//aotg_hcd_flush_queue(acthcd);
+		usb_hcd_poll_rh_status(hcd);
+	}
+
+	if ((acthcd->inserted == 0) && (connect_changed	== 1) && 
+	    (readb(acthcd->base + OTGSTATE) != AOTG_STATE_A_HOST)) {
+		acthcd->put_aout_msg = 1;
+		mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(2200));
+	}
+	acthcd->suspend_request_pend = 0;
+
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	enable_irq(acthcd->uhc_irq);
+	return;
+}
+
+static inline int aotg_print_ep_timeout(struct aotg_hcep *ep)
+{
+	int ret = 0;
+
+	if (ep == NULL) {
+		return ret;
+	}
+	if (ep->q != NULL) {
+		if (ep->q->timeout == 0)
+			return ret;
+
+		if (time_after(jiffies, ep->q->timeout)) {
+			ret = 1;
+			printk("ep->index:%x ep->mask:%x\n", ep->index, ep->mask);
+			printk("timeout:0x%x!\n", (unsigned int)ep->q->timeout);
+			ep->q->timeout = jiffies + HZ;
+		}
+	}
+	return ret;
+}
+
+static void aotg_check_trb_timer(unsigned long data)
+{
+	unsigned long flags;
+	struct aotg_hcep *ep;
+	int i;
+	struct aotg_hcd *acthcd = (struct aotg_hcd *)data;
+
+	if (unlikely(IS_ERR_OR_NULL((void *)data))) {
+		ACT_HCD_DBG
+		return;
+	}
+	if (acthcd->hcd_exiting != 0) {
+		ACT_HCD_DBG
+		return;
+	}
+
+	spin_lock_irqsave(&acthcd->lock, flags);
+	if (acthcd->check_trb_mutex) {
+		mod_timer(&acthcd->check_trb_timer, jiffies + msecs_to_jiffies(1));
+		spin_unlock_irqrestore(&acthcd->lock, flags);
+		return;
+	}
+
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->inep[i];
+		if (ep && (ep->ring) && (ep->ring->type == PIPE_BULK))
+				handle_ring_dma_tx(acthcd,i);
+	}
+
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->outep[i];
+		if (ep && (ep->ring) && (ep->ring->type == PIPE_BULK))
+			handle_ring_dma_tx(acthcd,i | AOTG_DMA_OUT_PREFIX);
+	}
+
+	mod_timer(&acthcd->check_trb_timer, jiffies + msecs_to_jiffies(3));
+
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	return;
+}
+
+static void aotg_hub_trans_wait_timer(unsigned long data)
+{
+	unsigned long flags;
+	struct aotg_hcep *ep;
+	int i, ret;
+	struct aotg_hcd *acthcd = (struct aotg_hcd *)data;
+
+	if (unlikely(IS_ERR_OR_NULL((void *)data))) {
+		ACT_HCD_DBG
+		return;
+	}
+	if (acthcd->hcd_exiting != 0) {
+		ACT_HCD_DBG
+		return;
+	}
+
+	//disable_irq_nosync(acthcd->uhc_irq);
+	disable_irq(acthcd->uhc_irq);
+	spin_lock_irqsave(&acthcd->lock, flags);
+
+	ep = acthcd->active_ep0;
+	ret = aotg_print_ep_timeout(ep);
+
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->inep[i];
+		ret |= aotg_print_ep_timeout(ep);
+	}
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->outep[i];
+		if (ep == NULL) {
+			continue;
+		}
+		ret |= aotg_print_ep_timeout(ep);
+
+		if (ep->fifo_busy) {
+			if ((ep->fifo_busy > 80) && (ep->fifo_busy % 80 == 0))  {
+				printk("ep->fifo_busy:%d\n", ep->fifo_busy);
+			}
+			if (ret == 0) {
+				tasklet_hi_schedule(&acthcd->urb_tasklet);
+				break;
+			}
+		}
+	}
+
+	if (ret != 0) {
+		tasklet_hi_schedule(&acthcd->urb_tasklet);
+	}
+	mod_timer(&acthcd->trans_wait_timer, jiffies + msecs_to_jiffies(500));
+
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	enable_irq(acthcd->uhc_irq);
+	return;
+}
+//FIXME
+static inline int start_transfer(struct aotg_hcd *acthcd, struct aotg_queue *q, struct aotg_hcep *ep)
+{
+	struct urb *urb = q->urb;
+	int retval = 0;
+
+	ep->urb_enque_cnt++;
+	q->length = urb->transfer_buffer_length;
+
+	/* do with hub connected. */
+	if (ep->has_hub) {
+		if (urb->dev->speed == USB_SPEED_HIGH) {
+			writeb(usb_pipedevice(urb->pipe), ep->reg_hcep_dev_addr);
+			writeb(urb->dev->portnum, ep->reg_hcep_port);
+		} else {
+			writeb((0x80 | usb_pipedevice(urb->pipe)), ep->reg_hcep_dev_addr);
+			if (urb->dev->speed == USB_SPEED_LOW) {
+				writeb(0x80 | urb->dev->portnum, ep->reg_hcep_port);
+			} else {
+				writeb(urb->dev->portnum, ep->reg_hcep_port);
+			}
+		}
+		//writeb(0, ep->reg_hcep_splitcs);
+	} else {
+		writeb(usb_pipedevice(urb->pipe), ep->reg_hcep_dev_addr);
+		writeb(urb->dev->portnum, ep->reg_hcep_port);
+	}
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		q->timeout = jiffies + HZ/2;
+		retval = handle_setup_packet(acthcd, q);
+		break;
+
+	default:
+		printk(KERN_ERR"%s err, check it pls!\n", __FUNCTION__);
+	}
+
+	return retval;
+}
+
+#if 0
+#define USB_CLASS_PER_INTERFACE		0	/* for DeviceClass */
+#define USB_CLASS_AUDIO			1
+#define USB_CLASS_COMM			2
+#define USB_CLASS_HID			3
+#define USB_CLASS_PHYSICAL		5
+#define USB_CLASS_STILL_IMAGE		6
+#define USB_CLASS_PRINTER		7
+#define USB_CLASS_MASS_STORAGE		8
+#define USB_CLASS_HUB			9
+#define USB_CLASS_CDC_DATA		0x0a
+#define USB_CLASS_CSCID			0x0b	/* chip+ smart card */
+#define USB_CLASS_CONTENT_SEC		0x0d	/* content security */
+#define USB_CLASS_VIDEO			0x0e
+#define USB_CLASS_WIRELESS_CONTROLLER	0xe0
+#define USB_CLASS_MISC			0xef
+#define USB_CLASS_APP_SPEC		0xfe
+#define USB_CLASS_VENDOR_SPEC		0xff
+#endif
+/*
+static void aotg_hcd_dump_isoc_packet(struct urb *urb)
+{
+	int i;
+	int number_of_packets;
+	u32 start_addr, addr;
+	unsigned int len;
+	
+	number_of_packets = urb->number_of_packets;
+	start_addr = (u32)urb->transfer_dma;
+
+	printk("----dump iso_packets( addr--len )----\n");
+	for (i = 0; i < number_of_packets; i++) {
+		addr = start_addr + urb->iso_frame_desc[i].offset;
+		len = urb->iso_frame_desc[i].length;
+		printk("packet%d : %u, %d\n", i, addr, len);
+	}
+	return;
+}
+*/
+static struct aotg_hcep	*aotg_hcep_alloc(struct usb_hcd *hcd, struct urb *urb)
+{
+	struct aotg_hcep *ep = NULL;
+	int pipe = urb->pipe;
+	int is_out = usb_pipeout(pipe);
+	int type = usb_pipetype(pipe);
+	int i, retval = 0;
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	u8 think_time;
+
+	ep = kzalloc(sizeof	*ep, GFP_ATOMIC);
+	if (NULL == ep)	{
+		dev_err(acthcd->dev, "alloc	ep failed\n");
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	ep->udev = usb_get_dev(urb->dev);
+	ep->epnum = usb_pipeendpoint(pipe);
+	ep->maxpacket = usb_maxpacket(ep->udev, urb->pipe, is_out);
+	ep->type = type;
+	ep->urb_enque_cnt = 0;
+	ep->urb_endque_cnt = 0;
+	ep->urb_stop_stran_cnt = 0;
+	ep->urb_unlinked_cnt = 0;
+#ifdef USBH_DEBUG
+	dev_info(acthcd->dev, "ep->epnum: %d, ep->maxpacket : %d, ep->type : %d\n", ep->epnum, ep->maxpacket, ep->type);
+#endif
+	ep->length = 0;
+	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), is_out, 0);
+
+	if (urb->dev->parent) {
+		if (urb->dev->tt) {
+			/* calculate in ns. */
+			think_time = (urb->dev->tt->think_time / 666);
+			printk("think_time:%d\n", think_time);
+			if (think_time <= 0) {
+				think_time = 1;
+			} else if (think_time > 4) {
+				think_time = 4;
+			}
+			think_time = think_time * 20;
+			writeb(think_time, acthcd->base + HCTRAINTERVAL);
+			printk("think_time:0x%x\n", readb(acthcd->base + HCTRAINTERVAL));
+			//printk("urb->dev->tt->hub:%p \n", urb->dev->tt->hub);
+		}
+
+		if ((urb->dev->parent->parent) && (urb->dev->parent != hcd->self.root_hub)) {
+			ep->has_hub = 1;
+			ep->hub_addr = 0x7f & readb(acthcd->base + FNADDR);
+		} else {
+			ep->has_hub = 0;
+		}
+	}
+
+	switch (type) {
+	case PIPE_CONTROL:
+		ep->reg_hcep_dev_addr = acthcd->base + HCEP0ADDR;
+		ep->reg_hcep_port = acthcd->base + HCEP0PORT;
+		ep->reg_hcep_splitcs = acthcd->base + HCEP0SPILITCS;
+
+		for (i = 0; i < MAX_EP_NUM; i++) {
+			if (acthcd->ep0[i] == NULL) {
+				ep->ep0_index = i;
+				acthcd->ep0[i] = ep;
+				break;
+			}
+		}
+		if (i == MAX_EP_NUM) {
+			ACT_HCD_ERR
+		}
+
+		ep->index = 0;
+		ep->mask = 0;
+		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 1, 0);
+		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 0, 0);
+
+		if (acthcd->active_ep0 == NULL) {
+			//writeb(ep->epnum, acthcd->base + HCEP0CTRL);
+			//writeb((u8)ep->maxpacket, acthcd->base + HCIN0MAXPCK);
+			//writeb((u8)ep->maxpacket, acthcd->base + HCOUT0MAXPCK);
+			usb_setbitsw(1, acthcd->base + HCOUTxIEN0);
+			usb_setbitsw(1, acthcd->base + HCINxIEN0);
+			writew(1, acthcd->base + HCOUTxIRQ0);
+			writew(1, acthcd->base + HCINxIRQ0);
+
+			if (ep->has_hub) {
+				usb_setbitsb(0x80, acthcd->base + FNADDR);
+			} else {
+				writeb(usb_pipedevice(urb->pipe), acthcd->base + FNADDR);
+			}
+			dev_info(acthcd->dev, "device addr : 0x%08x\n", readb(acthcd->base + FNADDR));
+		} else {
+			ACT_HCD_ERR
+		}
+		break;
+
+	case PIPE_BULK:
+		retval = aotg_hcep_config(acthcd, ep, EPCON_TYPE_BULK, EPCON_BUF_SINGLE, is_out);
+		if (retval < 0) {
+			dev_err(acthcd->dev, "PIPE_BULK, retval: %d\n", retval);
+			kfree(ep);
+			goto exit;
+		}
+		break;
+
+	case PIPE_INTERRUPT:
+		retval = aotg_hcep_config(acthcd, ep, EPCON_TYPE_INT, EPCON_BUF_SINGLE, is_out);
+		if (retval < 0) {
+			dev_err(acthcd->dev, "PIPE_INTERRUPT, retval: %d\n", retval);
+			kfree(ep);
+			goto exit;
+		}
+		ep->interval= urb->ep->desc.bInterval;
+		writeb(ep->interval, ep->reg_hcep_interval);		
+		//printk("urb->interval: %d\n", urb->interval);
+		//printk("urb->ep->desc.bInterval: %d, reg_interval:0x%x\n", 
+		//		urb->ep->desc.bInterval, readb(ep->reg_hcep_interval));
+		
+		break;
+
+	case PIPE_ISOCHRONOUS:
+		retval = aotg_hcep_config_iso(acthcd, ep, EPCON_TYPE_ISO, EPCON_BUF_SINGLE, is_out);
+		ep->iso_packets = (urb->ep->desc.wMaxPacketSize >> 11) & 3;
+		ep->interval = urb->ep->desc.bInterval;
+		writeb(ep->interval, ep->reg_hcep_interval);
+		usb_setb(ep->iso_packets << 4, ep->reg_hcepcon);
+		printk("iso_packets:%d, bInterval:%d, urb_interval:%d, reg_con:0x%x\n",
+					ep->iso_packets, ep->interval, urb->interval, readb(ep->reg_hcepcon));				
+		break;
+
+	default:
+		dev_err(acthcd->dev, "not support type, type: %d\n", type);
+		retval = -ENODEV;
+		kfree(ep);
+		goto exit;
+	}
+
+	if ((ep->udev->speed != USB_SPEED_HIGH) && ep->has_hub && (type == PIPE_INTERRUPT)) {
+		aotg_hcep_set_split_micro_frame(acthcd, ep);
+	}
+	ep->hep = urb->ep;
+	urb->ep->hcpriv = ep;
+	return ep;
+
+exit:
+	return NULL;
+}
+
+static int aotg_hub_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, unsigned mem_flags)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	struct aotg_queue *q=NULL;
+	unsigned long flags;
+	struct aotg_hcep *ep = NULL;
+	struct aotg_td *td, *next; 
+	int pipe = urb->pipe;
+	int type = usb_pipetype(pipe);
+	int retval = 0;
+	
+	if ((acthcd == NULL) || (act_hcd_ptr[acthcd->id] == NULL)) {
+		printk("aotg_hcd device had been removed...\n");
+		return -EIO;
+	}
+
+	if (acthcd->hcd_exiting != 0) {
+		dev_dbg(acthcd->dev, "aotg hcd exiting! type:%d\n", type);
+		return -ENODEV;
+	}
+
+	if (!(acthcd->port & USB_PORT_STAT_ENABLE)
+		|| (acthcd->port & (USB_PORT_STAT_C_CONNECTION << 16))
+		|| (acthcd->hcd_exiting != 0)
+		|| (acthcd->inserted == 0)
+	    	|| !HC_IS_RUNNING(hcd->state)) {
+		dev_err(acthcd->dev, "usbport dead or disable\n");
+		return -ENODEV;
+	}
+
+	spin_lock_irqsave(&acthcd->lock, flags);
+	
+	ep = urb->ep->hcpriv;
+	if ((unlikely(!urb->ep->enabled)) || (likely(ep) && unlikely(ep->error_count > 3))) {
+		printk("ep had been stopped!\n");
+		//spin_unlock_irqrestore(&acthcd->lock, flags);
+		//ep = (struct aotg_hcep *)urb->ep->hcpriv;
+		retval = -ENOENT;
+		goto exit0;
+	}
+	retval = usb_hcd_link_urb_to_ep(hcd, urb);
+	if (retval) {
+		dev_err(acthcd->dev, "<QUEUE>  usb_hcd_link_urb_to_ep error!! retval:0x%x\n",retval);
+		goto exit0;
+	}
+
+	if (likely(urb->ep->hcpriv)) {
+		ep = (struct aotg_hcep *)urb->ep->hcpriv;
+	} else {
+		ep = aotg_hcep_alloc(hcd, urb);
+		if (NULL == ep) {
+			dev_err(acthcd->dev, "<QUEUE> alloc ep failed\n");
+			retval = -ENOMEM;
+			goto exit1;
+		}
+		if (!usb_pipecontrol(pipe)) {
+			if (usb_pipeint(pipe)) 
+				ep->ring = aotg_alloc_ring(acthcd, ep, INTR_TRBS, GFP_ATOMIC);
+			else
+				ep->ring = aotg_alloc_ring(acthcd, ep, NUM_TRBS, GFP_ATOMIC);							
+			if (!ep->ring) {
+				dev_err(acthcd->dev, "alloc td_ring failed\n");
+				retval = -ENOMEM;
+				goto exit1;
+			}
+			INIT_LIST_HEAD(&ep->queue_td_list);
+			INIT_LIST_HEAD(&ep->enring_td_list);
+			INIT_LIST_HEAD(&ep->dering_td_list);
+
+			//enable_overflow_irq(acthcd, ep);
+		}
+		urb->ep->hcpriv	= ep;
+		if (type == PIPE_BULK)
+			mod_timer(&acthcd->check_trb_timer, jiffies + msecs_to_jiffies(100));
+	}
+
+	urb->hcpriv = hcd;
+
+	if (type == PIPE_CONTROL) {
+		q = aotg_hcd_get_queue(acthcd, urb, mem_flags);
+		if (unlikely(!q)) {
+			dev_err(acthcd->dev, "<QUEUE>  alloc dma queue failed\n");
+			spin_unlock_irqrestore(&acthcd->lock, flags);
+			return -ENOMEM;
+		}		
+
+		q->ep = ep;
+		q->urb = urb;
+		list_add_tail(&q->enqueue_list, &acthcd->hcd_enqueue_list);
+		aotg_dbg_put_q(q, usb_pipeendpoint(q->urb->pipe), usb_pipein(q->urb->pipe), 
+			q->urb->transfer_buffer_length);
+	} else if (type == PIPE_BULK) {
+		td = aotg_alloc_td(mem_flags);
+		if (!td) {
+			dev_err(acthcd->dev, "alloc td failed\n");
+			retval = -ENOMEM;
+			goto exit1;
+		}
+		td->urb = urb;
+
+		ep->urb_enque_cnt++;
+
+		if (list_empty(&ep->queue_td_list)) {
+			//ACT_HCD_DBG
+			retval = aotg_ring_enqueue_td(acthcd, ep->ring, td);
+			if (retval) {
+				list_add_tail(&td->queue_list, &ep->queue_td_list);
+				goto out;
+			} 
+
+			list_add_tail(&td->enring_list, &ep->enring_td_list);
+			ep->ring->enring_cnt++;
+		} else {
+			//ACT_HCD_DBG
+			list_add_tail(&td->queue_list, &ep->queue_td_list);
+		}
+
+		if (!list_empty(&ep->enring_td_list) && 
+								!is_ring_running(ep->ring)) {
+			//ACT_HCD_DBG
+			aotg_start_ring_transfer(acthcd, ep, urb);
+		}
+		
+	} else if (type == PIPE_INTERRUPT) {
+		if (unlikely(ep->ring->intr_inited == 0)) {
+			retval = aotg_ring_enqueue_intr_td(acthcd, ep->ring, ep, urb, GFP_ATOMIC);
+			if (retval) {
+				printk("%s, intr urb enqueue err!\n", __FUNCTION__);
+				goto exit1;
+			}
+			ep->ring->intr_started = 0;
+		}
+		ep->urb_enque_cnt++;
+		list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+			if (td->urb) {
+				continue;
+			} else {
+				td->urb = urb;
+				break;
+			}			
+		}
+		
+		if (unlikely(ep->ring->enqueue_trb->hw_buf_len != urb->transfer_buffer_length)) {
+			//printk("ep:%p,hw_buf_len:%d, urb_len:%d .......\n",ep,ep->ring->enqueue_trb->hw_buf_len,urb->transfer_buffer_length);
+			aotg_intr_chg_buf_len(acthcd,ep->ring,urb->transfer_buffer_length);
+			printk("WARNNING:interrupt urb length changed......\n");
+		}
+
+		if (ep->ring->intr_started == 0) {
+			ep->ring->intr_started = 1;			
+			//printk("%s, start ep%d intr transfer\n", __FUNCTION__, ep->index);
+			aotg_start_ring_transfer(acthcd, ep, urb);
+		}
+		
+		if (!is_ring_running(ep->ring)) { /*trb overflow or no urb*/
+			if (ep->is_out) {
+				aotg_start_ring_transfer(acthcd, ep, urb);
+			} else {
+				//if (ep->ring->ring_stopped == 0) {
+				if (aotg_intr_get_finish_trb(ep->ring) == 0) {
+					ep->ring->ring_stopped = 0;
+					aotg_reorder_intr_td(ep);
+					ep_enable(ep);
+					mb();
+					writel(DMACTRL_DMACS,ep->ring->reg_dmactrl);
+				//	printk("restart intr!\n");
+				} else ep->ring->ring_stopped = 1;
+			}
+		}
+	} else {// type == PIPE_ISOCHRONOUS
+		td = aotg_alloc_td(mem_flags);
+		if (!td) {
+			dev_err(acthcd->dev, "alloc td failed\n");
+			retval = -ENOMEM;
+			goto exit1;
+		}
+		td->urb = urb;
+		
+		ep->urb_enque_cnt++;
+
+		if (list_empty(&ep->queue_td_list)) {
+			//ACT_HCD_DBG
+			retval = aotg_ring_enqueue_isoc_td(acthcd, ep->ring, td);
+			if (retval) {
+				list_add_tail(&td->queue_list, &ep->queue_td_list);
+				goto out;
+			} 
+
+			list_add_tail(&td->enring_list, &ep->enring_td_list);
+			ep->ring->enring_cnt++;
+		} else {
+			//ACT_HCD_DBG
+			list_add_tail(&td->queue_list, &ep->queue_td_list);
+		}
+
+		if (!list_empty(&ep->enring_td_list) && !is_ring_running(ep->ring)) {
+			if (ep->ring->dequeue_trb != ep->ring->first_trb)
+				aotg_reorder_iso_td(acthcd, ep->ring);
+			aotg_start_ring_transfer(acthcd, ep, urb);
+		}
+	}
+out:
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	tasklet_hi_schedule(&acthcd->urb_tasklet);
+	return retval;
+exit1:
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
+exit0:
+	/* FIXME */
+	printk("never goto here, need to just\n");
+	if (unlikely(retval < 0) && ep) {
+		if (type == PIPE_CONTROL)	{
+			ACT_HCD_ERR
+			if (ep)
+				ep->q = NULL;
+			if(q)
+				aotg_hcd_release_queue(acthcd, q);
+		} else {
+			writel(DMACTRL_DMACC,ep->ring->reg_dmactrl);
+			ep_disable(ep);
+			/*if (!list_empty(&ep->queue_td_list)) {
+				list_for_each_entry_safe(td, next, &ep->queue_td_list, queue_list) {
+					list_del(&td->queue_list);
+					if (td)
+						kfree(td);
+				}
+			}
+		
+			if (!list_empty(&ep->enring_td_list)) {
+				list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+					list_del(&td->enring_list);
+					if (td)
+						kfree(td);
+				}
+			}*/
+		}
+	}
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	return retval;
+}
+
+static int aotg_hub_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	struct aotg_hcep *ep;
+	struct aotg_queue *q = NULL, *next, *tmp;
+	struct aotg_ring *ring;
+	struct aotg_td *td, *next_td;
+	unsigned long flags;
+	int retval = 0;
+	
+	if ((acthcd == NULL) || (act_hcd_ptr[acthcd->id] == NULL)) {
+		printk("aotg_hcd device had been removed...\n");
+		return -EIO;
+	}
+
+	spin_lock_irqsave(&acthcd->lock, flags);
+
+	retval = usb_hcd_check_unlink_urb(hcd, urb, status);
+	if (retval) {
+		printk("%s, retval:%d, urb not submitted or unlinked\n", __FUNCTION__, 
+				retval);
+		goto dequeue_out;
+	}
+
+	ep = (struct aotg_hcep *)urb->ep->hcpriv;
+	if (ep == NULL) {
+		ACT_HCD_ERR
+		retval = -EINVAL;
+		goto dequeue_out;
+	}
+
+	if (!usb_pipecontrol(urb->pipe)) {
+//		ACT_HCD_DBG
+		ep->urb_unlinked_cnt++;
+		ring = ep->ring;
+		
+		if (usb_pipeint(urb->pipe)) {
+			list_for_each_entry_safe(td, next_td, &ep->enring_td_list, enring_list) {
+				if (urb == td->urb) {
+					retval = aotg_ring_dequeue_intr_td(acthcd, ep, ring, td);
+					goto de_bulk;				
+				}
+			}
+			printk("%s, intr dequeue err\n", __FUNCTION__);
+		}
+
+		list_for_each_entry_safe(td, next_td, &ep->queue_td_list, queue_list) {
+			if (urb == td->urb) {
+				retval = aotg_ring_dequeue_td(acthcd, ring, td, TD_IN_QUEUE);
+				goto de_bulk;
+			}
+		}
+
+		list_for_each_entry_safe(td, next_td, &ep->enring_td_list, enring_list) {
+			mb();
+			if (urb == td->urb) {
+				retval = aotg_ring_dequeue_td(acthcd, ring, td, TD_IN_RING);
+				ep->urb_stop_stran_cnt++;
+				goto de_bulk;
+			} 
+		}
+
+		//pr_err("%s err, never be here, pls check it!\n", __func__);		
+		retval = -EINVAL;
+		goto dequeue_out;
+de_bulk:
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
+		spin_unlock(&acthcd->lock);
+		usb_hcd_giveback_urb(hcd, urb, status);
+		spin_lock(&acthcd->lock);
+
+		spin_unlock_irqrestore(&acthcd->lock, flags);
+		return retval;
+	}
+	
+	q = ep->q;
+
+	/* ep->mask currently equal to q->dma_no. */
+	if (q && (q->urb == urb)) {
+		writeb(EP0CS_HCSET,acthcd->base + EP0CS);
+		//dev_info(acthcd->dev, 
+			//"current dequeue -- ep->index: %d, dir : %s, type: %d, transfer_buffer_length: %d, actual_length:%d\n",
+			//ep->index, usb_pipeout(urb->pipe)?"out":"in", usb_pipetype(urb->pipe), 
+			//urb->transfer_buffer_length, urb->actual_length);
+
+		/* maybe finished in tasklet_finish_request. */
+		if (!list_empty(&q->finished_list)) {
+			if (q->finished_list.next != LIST_POISON1) {
+				list_del(&q->finished_list);
+			}
+		}
+
+		if (q->is_xfer_start) {
+			ep->urb_stop_stran_cnt++;
+			q->is_xfer_start = 0;
+		}
+	} else {
+		q = NULL;
+		list_for_each_entry_safe(tmp, next, &acthcd->hcd_enqueue_list, enqueue_list) {
+			if (tmp->urb == urb) {
+				list_del(&tmp->enqueue_list);
+				q = tmp;
+				ep = q->ep;
+				if (ep->q == q) {
+					ACT_HCD_DBG
+				}
+				break;
+			}
+		}
+	}
+
+	if (likely(q)) {
+		//ACT_HCD_DBG
+		//if (ep->q == q) 
+			//ep->q = NULL;
+		q->status = status;
+		list_add_tail(&q->dequeue_list, &acthcd->hcd_dequeue_list);
+		spin_unlock_irqrestore(&acthcd->lock, flags);
+		tasklet_schedule(&acthcd->urb_tasklet);
+		return retval;
+	} else {
+		ACT_HCD_ERR
+		printk("dequeue's urb not find in enqueue_list!\n");
+	}	
+
+dequeue_out:
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	return retval;
+}
+
+void urb_tasklet_func(unsigned long data)
+{
+	struct aotg_hcd *acthcd = (struct aotg_hcd *)data;
+	struct aotg_queue *q, *next;
+	struct aotg_hcep *ep;
+	struct urb *urb;
+	struct aotg_ring *ring;
+	struct aotg_td *td;
+	unsigned long flags;
+	int status;
+	struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+	int cnt = 0;
+	//static struct aotg_hcep * hcin_ep = NULL;
+
+	//spin_lock(&acthcd->tasklet_lock);
+
+	do {
+		status = (int)spin_is_locked(&acthcd->tasklet_lock);
+		if (status) {
+			acthcd->tasklet_retry = 1;
+			printk("locked, urb retry later!\n");
+			return;
+		}
+		cnt++;
+		/* sometimes tasklet_lock is unlocked, but spin_trylock still will be failed, 
+		 * maybe caused by the instruction of strexeq in spin_trylock, it will return failed   
+		 * if other cpu is accessing the nearby address of &acthcd->tasklet_lock.
+		 */
+		status = spin_trylock(&acthcd->tasklet_lock);
+		if ((!status) && (cnt > 10))  {
+			acthcd->tasklet_retry = 1;
+			printk("urb retry later!\n");
+			return;
+		}
+	} while (status == 0);
+
+	disable_irq(acthcd->uhc_irq);
+	spin_lock_irqsave(&acthcd->lock, flags);
+
+	for (cnt=1; cnt<MAX_EP_NUM; cnt++) {
+		ep = acthcd->inep[cnt];
+		if (ep && (ep->type == PIPE_INTERRUPT)) {
+			ring = ep->ring;
+			if (ring->ring_stopped) {
+				td = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+				if (!td)
+					continue;
+				urb = td->urb;
+				if (!urb)
+					continue;
+				intr_finish_td(acthcd, ring, td);
+			}
+		}
+	}
+	/* do dequeue task. */
+DO_DEQUEUE_TASK:
+	urb = NULL;
+	list_for_each_entry_safe(q, next, &acthcd->hcd_dequeue_list, dequeue_list) {
+		if (q->status < 0) {
+			urb = q->urb;
+			ep = q->ep;
+			if (ep) {
+				ep->urb_unlinked_cnt++;
+				//ep->q = NULL;
+			}
+			list_del(&q->dequeue_list);
+			status = q->status;
+			tasklet_finish_request(acthcd, q, status);
+			hcd = bus_to_hcd(urb->dev->bus);
+			break;
+		} else {
+			ACT_HCD_ERR
+		}
+	}
+	if (urb != NULL) {
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
+		spin_unlock_irqrestore(&acthcd->lock, flags);
+		/* in usb_hcd_giveback_urb, complete function may call new urb_enqueue. */ 
+		usb_hcd_giveback_urb(hcd, urb, status);
+		spin_lock_irqsave(&acthcd->lock, flags);
+		goto DO_DEQUEUE_TASK;
+	}
+
+	/* do finished task. */
+DO_FINISH_TASK:
+	urb = NULL;
+	list_for_each_entry_safe(q, next, &acthcd->hcd_finished_list, finished_list) {
+		if (q->finished_list.next != LIST_POISON1) {
+			list_del(&q->finished_list);
+		} else {
+			ACT_HCD_ERR
+			break;
+		}
+		status = q->status;
+		tasklet_finish_request(acthcd, q, status);
+
+		hcd = aotg_to_hcd(acthcd);
+		urb = q->urb;
+		ep = q->ep;
+		if (urb != NULL) {
+			break;
+		}
+	}
+	if (urb != NULL) {
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+		spin_unlock_irqrestore(&acthcd->lock, flags);
+
+		/* in usb_hcd_giveback_urb, complete function may call new urb_enqueue. */ 
+		usb_hcd_giveback_urb(hcd, urb, status);
+
+		spin_lock_irqsave(&acthcd->lock, flags);
+		goto DO_FINISH_TASK;
+	}
+
+//DO_ENQUEUE_TASK:
+	/* do enqueue task. */
+	/* start transfer directly, don't care setup appearing in bulkout. */
+	list_for_each_entry_safe(q, next, &acthcd->hcd_enqueue_list, enqueue_list) {
+		urb = q->urb;
+		ep = q->ep;
+
+		/* deal with controll request. */
+		if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
+			if ((acthcd->active_ep0 != NULL) && (acthcd->active_ep0->q != NULL)) {
+				acthcd->ep0_block_cnt++;
+				//ACT_HCD_DBG
+				if ((acthcd->ep0_block_cnt % 10) == 0) {
+					ACT_HCD_DBG
+					printk("cnt:%d\n", acthcd->ep0_block_cnt);
+					acthcd->ep0_block_cnt = 0;
+					//aotg_hub_urb_dequeue(hcd, acthcd->active_ep0->q->urb, -ETIMEDOUT);
+				}
+				continue;
+			} else {
+				acthcd->ep0_block_cnt = 0;
+				goto BEGIN_START_TANSFER;
+			}
+		} 
+
+		/* deal with new bulk in request. */
+		if ((usb_pipetype(urb->pipe) == PIPE_BULK) && (usb_pipein(urb->pipe))) {
+			if (ep->q != NULL) {
+				continue;
+			}
+			goto BEGIN_START_TANSFER;
+		}
+
+		/* deal with bulk out request. */
+		if ((usb_pipetype(urb->pipe) == PIPE_BULK) && (usb_pipeout(urb->pipe))) {
+			if (ep->q != NULL) {
+				continue;
+			}
+			if ((EPCS_BUSY & readb(ep->reg_hcepcs)) != 0) {
+				ep->fifo_busy++;
+				mod_timer(&acthcd->trans_wait_timer, jiffies + msecs_to_jiffies(3));
+				continue;
+			} else {
+				ep->fifo_busy = 0;
+			}
+			goto BEGIN_START_TANSFER;
+		}
+
+BEGIN_START_TANSFER:
+		list_del(&q->enqueue_list);
+		status = start_transfer(acthcd, q, ep);
+
+		if (unlikely(status < 0)) {
+			ACT_HCD_ERR
+			hcd = bus_to_hcd(urb->dev->bus);
+			aotg_hcd_release_queue(acthcd, q);
+
+			usb_hcd_unlink_urb_from_ep(hcd, urb);
+			spin_unlock_irqrestore(&acthcd->lock, flags);
+			usb_hcd_giveback_urb(hcd, urb, status);
+			spin_lock_irqsave(&acthcd->lock, flags);
+		}
+		//spin_unlock_irqrestore(&acthcd->lock, flags);
+		//enable_irq(acthcd->uhc_irq);
+		//spin_unlock(&acthcd->tasklet_lock);
+		//return;
+	}
+
+	if (acthcd->tasklet_retry != 0) {
+		acthcd->tasklet_retry = 0;
+		goto DO_DEQUEUE_TASK;
+	}
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	enable_irq(acthcd->uhc_irq);
+	spin_unlock(&acthcd->tasklet_lock);
+	return;
+}
+
+static void aotg_hub_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+{
+	int i;
+	int index;
+	unsigned long flags;
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	struct aotg_hcep *ep = hep->hcpriv;
+	
+	if (!ep)
+		return;
+
+	/* assume we'd just wait for the irq */
+//	for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++)
+//		msleep(3);
+
+	if (in_irq()) {
+		disable_irq_nosync(acthcd->uhc_irq);
+	} else {
+		disable_irq(acthcd->uhc_irq);
+	}
+	spin_lock_irqsave(&acthcd->lock, flags);
+
+//	usb_put_dev(ep->udev);
+	index = ep->index;
+	if (index == 0) {
+		acthcd->ep0[ep->ep0_index] = NULL;
+		if (acthcd->active_ep0 == ep) {
+			acthcd->active_ep0 = NULL;
+		}
+		for (i = 0; i < MAX_EP_NUM; i++) {
+			if (acthcd->ep0[i] != NULL) {
+				break;
+			}
+		}
+		if (i == MAX_EP_NUM) {
+			usb_clearbitsw(1, acthcd->base + HCOUTxIEN0);
+			usb_clearbitsw(1, acthcd->base + HCINxIEN0);
+			writew(1, acthcd->base + HCOUTxIRQ0);
+			writew(1, acthcd->base + HCINxIRQ0);
+		}
+	} else {
+		ep_disable(ep);
+		if (ep->mask & USB_HCD_OUT_MASK) {
+			acthcd->outep[index] = NULL;
+		} else {
+			acthcd->inep[index] = NULL;
+		}
+//		pio_irq_disable(acthcd, ep->mask);
+//		pio_irq_clear(acthcd, ep->mask);
+		release_fifo_addr(acthcd, ep->fifo_addr);
+	}
+	
+	hep->hcpriv = NULL;
+
+	if(ep->ring){
+		printk("%s\n", __FUNCTION__);
+		
+		aotg_stop_ring(ep->ring);
+		if (ep->ring->type == PIPE_INTERRUPT) {
+			printk("%s, ep%d dma buf free\n", __FUNCTION__, ep->index);
+			aotg_intr_dma_buf_free(acthcd, ep->ring);
+		}
+			
+		aotg_free_ring(acthcd, ep->ring);
+	}
+		
+	dev_info(acthcd->dev, "<EP DISABLE> ep%d index %d from ep [%s]\n", 
+			ep->epnum, index, 
+			ep->mask & USB_HCD_OUT_MASK ? "out":"in");
+
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	enable_irq(acthcd->uhc_irq);
+	kfree(ep);
+	return;
+}
+
+static int aotg_hcd_get_frame(struct usb_hcd *hcd)
+{
+	struct timeval	tv;
+
+	do_gettimeofday(&tv);
+	return tv.tv_usec / 1000;
+}
+
+static int aotg_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct aotg_hcd *acthcd;
+	unsigned long flags;
+	int retval = 0;
+
+	acthcd = hcd_to_aotg(hcd);
+	local_irq_save(flags);
+	if (!HC_IS_RUNNING(hcd->state))
+		goto done;
+
+	if ((acthcd->port & AOTG_PORT_C_MASK) != 0) {
+		*buf = (1 << 1);
+		HUB_DEBUG("<HUB STATUS>port status %08x has changes\n", acthcd->port);
+		retval = 1;
+	}
+done:
+	local_irq_restore(flags);
+	return retval;
+}
+
+static __inline__ void port_reset(struct aotg_hcd *acthcd)
+{
+	HCD_DEBUG("<USB> port reset\n");
+	writeb(0x1<<6 | 0x1<<5, acthcd->base + HCPORTCTRL);	/*portrst & 55ms */
+}
+
+static void port_power(struct aotg_hcd *acthcd, int is_on)
+{
+	struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+	//struct device *dev = hcd->self.controller;
+
+	/* hub is inactive unless the port is powered */
+	if (is_on) {
+		hcd->self.controller->power.power_state = PMSG_ON;
+		dev_dbg(acthcd->dev, "<USB> power on\n");
+	} else {
+		hcd->self.controller->power.power_state = PMSG_SUSPEND;
+		dev_dbg(acthcd->dev, "<USB> power off\n");
+	}
+}
+
+static void port_suspend(struct aotg_hcd *acthcd)
+{
+	usb_clearbitsb(OTGCTRL_BUSREQ, acthcd->base + OTGCTRL);
+}
+
+static void port_resume(struct aotg_hcd *acthcd)
+{
+	usb_setbitsb(OTGCTRL_BUSREQ, acthcd->base + OTGCTRL);
+}
+
+static int aotg_hcd_start(struct usb_hcd *hcd)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	//struct device *dev = hcd->self.controller;
+	//struct aotg_plat_data *data = dev->platform_data;
+	int retval = 0;
+	unsigned long flags;
+	
+	dev_info(acthcd->dev, "<HCD> start\n");
+	
+	local_irq_save(flags);
+	hcd->state = HC_STATE_RUNNING;
+	hcd->uses_new_polling = 1;
+	local_irq_restore(flags);
+	
+	return retval;
+
+}
+
+static void aotg_hcd_stop(struct usb_hcd *hcd)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	//struct device *dev = hcd->self.controller;
+	//struct aotg_plat_data *data = dev->platform_data;
+	unsigned long flags;
+	
+	dev_info(acthcd->dev, "<HCD> stop\n");
+	
+	local_irq_save(flags);
+	hcd->state = HC_STATE_HALT;
+	acthcd->port = 0;
+	acthcd->rhstate = AOTG_RH_POWEROFF;
+	local_irq_restore(flags);
+	return;
+}
+
+#ifdef	CONFIG_PM
+
+static int aotg_hub_suspend(struct usb_hcd *hcd)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+
+	if ((hcd == NULL) || (acthcd == NULL)) {
+		ACT_HCD_ERR
+		return 0;
+	}
+	acthcd->suspend_request_pend = 1;
+	port_suspend(acthcd);
+	
+	return 0;
+}
+
+static int
+aotg_hub_resume(struct usb_hcd *hcd)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	
+	port_resume(acthcd);
+
+	return 0;
+}
+
+#else
+
+#define	aotg_hub_suspend	NULL
+#define	aotg_hub_resume		NULL
+
+#endif
+
+static __inline__ void aotg_hub_descriptor(struct usb_hub_descriptor *desc)
+{
+	memset(desc, 0, sizeof *desc);
+	desc->bDescriptorType = 0x29;
+	desc->bDescLength = 9;
+	desc->wHubCharacteristics = (__force __u16)
+	    (__constant_cpu_to_le16(0x0001));
+	desc->bNbrPorts = 1;
+	//desc->bitmap[0] = 1 << 1;
+	//desc->bitmap[1] = 0xff;
+}
+
+static int aotg_hub_control(struct usb_hcd *hcd,
+			    u16 typeReq,
+			    u16 wValue, u16 wIndex, char *buf, u16 wLength)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	unsigned long flags;
+	int retval = 0;
+
+	if (in_irq()) {
+		disable_irq_nosync(acthcd->uhc_irq);
+	} else {
+		disable_irq(acthcd->uhc_irq);
+	}
+	spin_lock_irqsave(&acthcd->lock, flags);
+
+	if (!HC_IS_RUNNING(hcd->state)) {
+		dev_err(acthcd->dev, "<HUB_CONTROL> hc state is not HC_STATE_RUNNING\n");
+		spin_unlock_irqrestore(&acthcd->lock, flags);
+		enable_irq(acthcd->uhc_irq);
+		return -EPERM;
+	}
+	HUB_DEBUG("<HUB_CONTROL> typeReq:%x, wValue:%04x, wIndex: %04x, wLength: %04x\n", typeReq, wValue, wIndex, wLength);
+
+	switch (typeReq) {
+	case ClearHubFeature:
+		HUB_DEBUG("<HUB_CONTROL> ClearHubFeature, wValue:%04x, wIndex: %04x, wLength: %04x\n",
+		     wValue, wIndex, wLength);
+		break;
+	case ClearPortFeature:
+		HUB_DEBUG("<HUB_CONTROL> ClearPortFeature, wValue:%04x, wIndex: %04x, wLength: %04x\n",
+		     wValue, wIndex, wLength);
+
+		if (wIndex != 1 || wLength != 0)
+			goto hub_error;
+		HUB_DEBUG("<HUB_CONTROL> before clear operation,the port status is %08x\n", acthcd->port);
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			acthcd->port &= ~(USB_PORT_STAT_ENABLE
+					  | USB_PORT_STAT_LOW_SPEED
+					  | USB_PORT_STAT_HIGH_SPEED);
+			acthcd->rhstate = AOTG_RH_DISABLE;
+			if (acthcd->port & USB_PORT_STAT_POWER)
+				port_power(acthcd, 0);
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			HUB_DEBUG("<HUB_CONTROL>clear suspend feathure\n");
+			//port_resume(acthcd);
+			acthcd->port &= ~(1 << wValue);
+			break;
+		case USB_PORT_FEAT_POWER:
+			acthcd->port = 0;
+			acthcd->rhstate = AOTG_RH_POWEROFF;
+			port_power(acthcd, 0);
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+		case USB_PORT_FEAT_C_SUSPEND:
+		case USB_PORT_FEAT_C_CONNECTION:
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+		case USB_PORT_FEAT_C_RESET:
+			acthcd->port &= ~(1 << wValue);
+			break;
+		default:
+			goto hub_error;
+		}
+		HUB_DEBUG("<HUB_CONTROL> after clear operation,the port status is %08x\n", acthcd->port);
+		break;
+	case GetHubDescriptor:
+		HUB_DEBUG("<HUB_CONTROL> GetHubDescriptor, wValue:%04x, wIndex: %04x, wLength: %04x\n",
+		     wValue, wIndex, wLength);
+		aotg_hub_descriptor((struct usb_hub_descriptor *)buf);
+		break;
+	case GetHubStatus:
+		HUB_DEBUG("<HUB_CONTROL> GetHubStatus, wValue:%04x, wIndex: %04x, wLength: %04x\n",
+		     wValue, wIndex, wLength);
+
+		*(__le32 *) buf = __constant_cpu_to_le32(0);
+		break;
+	case GetPortStatus:
+		HUB_DEBUG("<HUB_CONTROL> GetPortStatus, wValue:%04x, wIndex: %04x, wLength: %04x\n",
+		     wValue, wIndex, wLength);
+
+		if (wIndex != 1)
+			goto hub_error;
+		*(__le32 *) buf = cpu_to_le32(acthcd->port);
+		HUB_DEBUG("<HUB_CONTROL> the port status is %08x\n ",
+			 acthcd->port);
+		break;
+	case SetHubFeature:
+		HUB_DEBUG("<HUB_CONTROL> SetHubFeature, wValue: %04x,wIndex: %04x, wLength: %04x\n",
+		     wValue, wIndex, wLength);
+		goto hub_error;
+		break;
+	case SetPortFeature:
+		HUB_DEBUG("<HUB_CONTROL> SetPortFeature, wValue:%04x, wIndex: %04x, wLength: %04x\n",
+		     wValue, wIndex, wLength);
+
+		switch (wValue) {
+		case USB_PORT_FEAT_POWER:
+			if (unlikely(acthcd->port & USB_PORT_STAT_POWER))
+				break;
+			acthcd->port |= (1 << wValue);
+			acthcd->rhstate = AOTG_RH_POWERED;
+			port_power(acthcd, 1);
+			break;
+		case USB_PORT_FEAT_RESET:
+			port_reset(acthcd);
+			/* if it's already enabled, disable */
+			acthcd->port &= ~(USB_PORT_STAT_ENABLE
+					  | USB_PORT_STAT_LOW_SPEED
+					  | USB_PORT_STAT_HIGH_SPEED);
+			acthcd->port |= (1 << wValue);
+			mdelay(2);
+			acthcd->rhstate = AOTG_RH_RESET;
+			usb_setbitsb(USBIEN_URES, acthcd->base + USBIEN);
+			/*enable reset irq */
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			/*acthcd->port |= USB_PORT_FEAT_SUSPEND;*/
+			acthcd->port |= (1 << wValue);
+			acthcd->rhstate = AOTG_RH_SUSPEND;
+			//port_suspend(acthcd);
+			break;
+		default:
+			if (acthcd->port & USB_PORT_STAT_POWER)
+				acthcd->port |= (1 << wValue);
+		}
+		break;
+	default:
+hub_error:
+		retval = -EPIPE;
+		dev_err(acthcd->dev, "<HUB_CONTROL> hub control error\n");
+		break;
+
+	}
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	enable_irq(acthcd->uhc_irq);
+
+	return retval;
+}
+
+static void aotg_DD_set_phy(void __iomem *base, u8 reg, u8 value)
+{
+	u8 addrlow, addrhigh;
+	int time = 1;
+
+	addrlow = reg & 0x0f;
+	addrhigh = (reg >> 4) & 0x0f;
+
+	/*write vstatus: */
+	writeb(value, base + VDSTATUS);
+	mb();
+
+	/*write vcontrol: */
+	writeb(addrlow | 0x10, base + VDCTRL);
+	udelay(time); //the vload period should > 33.3ns
+	writeb(addrlow & 0x0f, base + VDCTRL);
+	udelay(time);
+	mb();
+	writeb(addrlow | 0x10, base + VDCTRL);
+	udelay(time);
+	writeb(addrhigh | 0x10, base + VDCTRL);
+	udelay(time);
+	writeb(addrhigh & 0x0f, base + VDCTRL);
+	udelay(time);
+	writeb(addrhigh | 0x10, base + VDCTRL);
+	udelay(time);
+	return;
+}
+
+static void aotg_DD_set_phy_init(struct aotg_hcd *acthcd)
+{
+	int slew_rate,tx_bias;
+	if (acthcd->id) {
+		slew_rate = aotg1_slew_rate;
+		tx_bias = aotg1_tx_bias;
+	} else {
+		slew_rate = aotg0_slew_rate;
+		tx_bias = aotg0_tx_bias;
+	}
+	
+	aotg_DD_set_phy(acthcd->base, 0xf4,(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0));
+	aotg_DD_set_phy(acthcd->base, 0xe0,(1<<5) |(1<<4)|(0<<3)|(1<<2)|(1<<0));
+
+	aotg_DD_set_phy(acthcd->base, 0xf4,(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0));
+	if((slew_rate >=0) && (slew_rate <= 7))
+		aotg_DD_set_phy(acthcd->base, 0xe1,(slew_rate<<5)|(0<<4)|(1<<3)|(1<<2)|(3<<0));
+	else
+		aotg_DD_set_phy(acthcd->base, 0xe1,(3<<5) |(0<<4)|(1<<3)|(1<<2)|(3<<0));
+
+	aotg_DD_set_phy(acthcd->base, 0xf4,(1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0));
+	aotg_DD_set_phy(acthcd->base, 0xe6,(1<<7) |(4<<4)|(1<<3)|(0<<2)|(3<<0));
+
+	aotg_DD_set_phy(acthcd->base, 0xf4,(1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0));
+	//aotg_DD_set_phy(acthcd->base, 0xe7,(7<<4)|(0<<1)|(1<<0));
+	aotg_DD_set_phy(acthcd->base, 0xe7,(9<<4)|(0<<1)|(1<<0));
+
+	aotg_DD_set_phy(acthcd->base, 0xf4,(1<<7) |(1<<5)|(1<<4)|(2<<2)|(3<<0));
+	aotg_DD_set_phy(acthcd->base, 0xe0,(1<<5) |(1<<4)|(0<<3)|(0<<2)|(1<<0));
+	
+	
+	aotg_DD_set_phy(acthcd->base, 0xf4,(1<<7) |(0<<5)|(1<<4)|(2<<2)|(3<<0));
+	if((tx_bias >=0) && (tx_bias <= 15))
+		aotg_DD_set_phy(acthcd->base, 0xe4, (0xc<<4)|(tx_bias<<0));
+	else
+		aotg_DD_set_phy(acthcd->base, 0xe4, (0xc<<4)|(4<<0));
+	
+	aotg_DD_set_phy(acthcd->base, 0xf0,(1<<7) |(1<<6) |(1<<5)|(1<<4)|(1<<3)|(1<<2)|(0<<1)|(0<<0));
+	return;
+}
+
+static void aotg_hcd_clk_enable(struct aotg_hcd *acthcd, int is_enable)
+{
+	struct aotg_plat_data *data = acthcd->port_specific;
+#if 0	
+	__u32 tmp;
+	struct clk *dev_pll = NULL;
+	struct clk *usb_pll = NULL;
+
+	if (is_enable) {
+		dev_pll = clk_get_sys(CLK_NAME_DEVPLL, NULL); /*\B8\F9\BE\DDclk_name\BB\F1ȡclk\BDṹ\CC\E5*/
+		if (IS_ERR(dev_pll)) {
+			printk("get dev_pll err!\n");
+			return;
+		}
+		
+		usb_pll = clk_get_sys(CLK_NAME_USBPLL, NULL); /*\B8\F9\BE\DDclk_name\BB\F1ȡclk\BDṹ\CC\E5*/
+		if (IS_ERR(usb_pll)) {
+			ACT_HCD_ERR
+		}
+		clk_enable(dev_pll);  /*enable clk*/
+		//clk_enable(usb_pll);  /*enable clk*/
+
+		usb_setbitsl(data->usbpll_bits, data->usbpll);
+		tmp = readl(data->usbpll);
+
+		hcd_2clk_bits_en |= 0x1 << acthcd->id;
+		
+	} else {
+		if (!hcd_2clk_bits_en) {
+			return;
+		}
+		hcd_2clk_bits_en &= ~(0x1 << acthcd->id);
+		dev_pll = clk_get_sys(CLK_NAME_DEVPLL, NULL); /*\B8\F9\BE\DDclk_name\BB\F1ȡclk\BDṹ\CC\E5*/
+		if (IS_ERR(dev_pll)) {
+			printk("get dev_pll err!\n");
+			return;
+		}
+		
+		usb_pll = clk_get_sys(CLK_NAME_USBPLL, NULL); /*\B8\F9\BE\DDclk_name\BB\F1ȡclk\BDṹ\CC\E5*/
+
+		if (IS_ERR(usb_pll)) {			
+			ACT_HCD_ERR;
+		}
+		usb_clearbitsl(data->usbpll_bits, data->usbpll);
+
+		clk_disable(dev_pll);  /*disable clk*/
+		//clk_disable(usb_pll);  /*disable clk*/
+	}
+#endif
+
+	if (is_enable) {
+		usb_setbitsl(data->usbpll_bits, data->usbpll);
+	} else {
+		usb_clearbitsl(data->usbpll_bits, data->usbpll);
+	}
+	
+	return;
+}
+
+static int aotg_hcd_controller_reset(struct aotg_hcd *acthcd)
+{
+	struct aotg_plat_data *data = acthcd->port_specific;
+	int i = 0;
+
+	usb_clearbitsl(data->devrst_bits, data->devrst);
+	udelay(1);
+	usb_setbitsl(data->devrst_bits, data->devrst);
+
+	while (((readb(acthcd->base + USBERESET) & USBERES_USBRESET) != 0) && (i < 300000)) {
+		i++;
+		udelay(1);
+	}
+
+	if (!(readb(acthcd->base + USBERESET) & USBERES_USBRESET)) {
+		dev_info(acthcd->dev, "usb reset OK: %x.\n", readb(acthcd->base + USBERESET));
+	} else {
+		dev_err(acthcd->dev, "usb reset ERROR: %x.\n", readb(acthcd->base + USBERESET));
+		return -EBUSY;
+	}
+	return 0;
+}
+
+static void aotg_hcd_hardware_init(struct aotg_hcd *acthcd)
+{
+	u8 val8;
+	unsigned long flags;
+	struct aotg_plat_data *data = acthcd->port_specific;
+
+	owl_powergate_power_on(acthcd->id == 0 ?
+		OWL_POWERGATE_USB2_0 : OWL_POWERGATE_USB2_1);
+	//module_clk_enable(MOD_ID_USB2);
+	module_clk_enable(acthcd->id == 0 ?
+		MOD_ID_USB2_0 : MOD_ID_USB2_1);
+	aotg_hcd_clk_enable(acthcd, 1);
+
+	local_irq_save(flags);
+	aotg_hcd_controller_reset(acthcd);
+	/* fpga : new DMA mode */
+	writel(0x1, acthcd->base + HCDMABCKDOOR);
+
+	/* USBH0_ECS: set soft vbus and id, 
+	 * bit29 -- host disconnect detection enable; 
+	 * bit28 -- connect and disconnect enable.
+	 * bit27 -- softid value; 
+	 * bit26 -- softid enalbe 
+	 * bit25 -- softvbus value.
+	 * bit24 -- softvbus enable.
+	 * bit13:14 -- VBUS detection threshold 
+	 * bit7   -- PLL LDO enable
+	 * bit 4:6 -- vbus threshold 3.43~3.57. */ 
+	writel((0x37 << 24) | (0x10 << 13) | (0xb << 4), data->usbecs);
+	udelay(100);
+	aotg_DD_set_phy_init(acthcd);
+
+	/***** TA_BCON_COUNT *****/
+	writeb(0x0, acthcd->base + TA_BCON_COUNT);     		//110ms
+	/****HNP setting ********/
+	//Writeb(acthcd->base + USBH_BKDOOR, (Readb(USBH_BKDOOR)| 0x08));    
+	//Writeb(acthcd->base + USBH_BKDOOR, (Readb(USBH_BKDOOR)| 0x04));    //set the tx_pre
+
+	/*set TA_AIDL_BDIS timeout never generate */
+	writeb(0xff, acthcd->base + TAAIDLBDIS);
+	/*set TA_WAIT_BCON timeout never generate */
+	writeb(0xff, acthcd->base + TAWAITBCON);
+	/*set TB_VBUS_DISCHARGE_PLS timeout value = 40.68ms*/
+	writeb(0x28, acthcd->base + TBVBUSDISPLS);
+	/*set TA_WAIT_BCON timeout never generate*/
+	usb_setbitsb(1 << 7, acthcd->base + TAWAITBCON);
+
+	writew(0x1000, acthcd->base + VBUSDBCTIMERL);
+//	writeb(0x40, acthcd->base + USBCS);
+
+	val8 = readb(acthcd->base + BKDOOR);
+	if (data && data->no_hs) {
+		val8 |= (1 << 7);
+	} else {
+		val8 &= ~(1 << 7);
+	}
+	if (is_ls_device[acthcd->id])
+		val8 |= (1<<7);
+	writeb(val8, acthcd->base + BKDOOR);
+	mb();
+
+	local_irq_restore(flags);
+	//writeb(0xff, acthcd->base + HCTRAINTERVAL);
+
+	return;
+}
+
+static int aotg_hcd_init(struct usb_hcd *hcd, struct platform_device *pdev)
+{
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	int retval = 0;
+	int i;
+
+	/*init software state */
+	spin_lock_init(&acthcd->lock);
+	spin_lock_init(&acthcd->tasklet_lock);
+	acthcd->tasklet_retry = 0;
+	//acthcd->dev = &pdev->dev;
+	acthcd->port_specific = pdev->dev.platform_data;
+	acthcd->port = 0;
+	acthcd->rhstate = AOTG_RH_POWEROFF;
+	acthcd->inserted = 0;
+
+	INIT_LIST_HEAD(&acthcd->hcd_enqueue_list);
+	INIT_LIST_HEAD(&acthcd->hcd_dequeue_list);
+	INIT_LIST_HEAD(&acthcd->hcd_finished_list);
+	tasklet_init(&acthcd->urb_tasklet, urb_tasklet_func, (unsigned long)acthcd);
+
+#if 0
+	for (i = 0; i < PERIODIC_SIZE; i++) {
+		acthcd->load[i] = 0;
+		acthcd->periodic[i] = NULL;
+	}
+#endif
+
+	acthcd->active_ep0 = NULL;
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		acthcd->ep0[i] = NULL;
+		acthcd->inep[i] = NULL;
+		acthcd->outep[i] = NULL;
+	}
+
+	acthcd->fifo_map[0] = 1<<31;
+	acthcd->fifo_map[1] = 1<<31 | 64;
+	for (i = 2; i < 64; i++) {
+		acthcd->fifo_map[i] = 0;
+	}
+
+	acthcd->put_aout_msg = 0;
+	acthcd->discon_happened = 0;
+	acthcd->uhc_irq = 0;
+	acthcd->check_trb_mutex = 0;
+	for (i = 0; i < AOTG_QUEUE_POOL_CNT; i++) {
+		acthcd->queue_pool[i] = NULL;
+	}
+
+	return retval;
+}
+
+static const char platform_drv_name[] = "aotg_hcd";
+static const char hcd_driver_name[] = "aotg_hub_hcd";
+
+#define AOTG_BUF_NEED_MAP(x, y)	((x != NULL) && (((unsigned long)x & 0x3) == 0))
+//#define AOTG_BUF_NEED_MAP(x, y)	((x != NULL) && ((y & 0x3) == 0))
+
+static int aotg_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+				      gfp_t mem_flags)
+{
+	int ret = 0;
+
+	if (usb_pipetype(urb->pipe) != PIPE_INTERRUPT) {
+		ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+	}
+	return ret;
+}
+
+static void aotg_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	if (usb_pipetype(urb->pipe) != PIPE_INTERRUPT) {
+
+		usb_hcd_unmap_urb_for_dma(hcd, urb);
+	}
+	return;
+}
+
+static struct hc_driver act_hc_driver = {
+	.description = hcd_driver_name,
+	.hcd_priv_size = sizeof(struct aotg_hcd),
+	.product_desc = DRIVER_DESC,
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = aotg_hub_irq,
+	.flags = HCD_USB2 | HCD_MEMORY,
+
+	/* Basic lifecycle operations */
+	.start = aotg_hcd_start,
+	.stop = aotg_hcd_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = aotg_hub_urb_enqueue,
+	.urb_dequeue = aotg_hub_urb_dequeue,
+
+	.map_urb_for_dma	= aotg_map_urb_for_dma,
+	.unmap_urb_for_dma	= aotg_unmap_urb_for_dma,
+
+	.endpoint_disable = aotg_hub_endpoint_disable,
+
+	/*
+	 * periodic schedule support
+	 */
+	.get_frame_number = aotg_hcd_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = aotg_hub_status_data,
+	.hub_control = aotg_hub_control,
+
+	.bus_suspend =        aotg_hub_suspend,
+	.bus_resume =         aotg_hub_resume,
+};
+
+struct of_device_id aotg_hcd_of_match[] = {
+	{.compatible = "actions,owl-usb-2.0-0",.data = &aotg_data0},
+	{.compatible = "actions,owl-usb-2.0-1",.data = &aotg_data1},
+	{},
+};
+MODULE_DEVICE_TABLE(of, aotg_hcd_of_match);
+
+static int aotg_platform_device_init(struct platform_device *pdev)
+{
+	struct device_node *of_node;
+	enum of_gpio_flags flags;
+
+	of_node = of_find_compatible_node(NULL, NULL, aotg_hcd_of_match[pdev->id].compatible);
+	if (NULL == of_node) {
+		dev_err(&pdev->dev, "can't find usbh%d dts node\n",pdev->id);
+		return -1;
+	}
+
+	if (!of_find_property(of_node, "vbus_otg_en_gpio", NULL)) {
+		pr_info("can't find vbus_otg_en_gpio config\n");
+		vbus_otg_en_gpio[pdev->id][0] = -1;
+	} else {
+		vbus_otg_en_gpio[pdev->id][0] = of_get_named_gpio_flags(of_node, "vbus_otg_en_gpio",0, &flags);
+		vbus_otg_en_gpio[pdev->id][1] = flags & 0x01;
+		if (gpio_request(vbus_otg_en_gpio[pdev->id][0], aotg_hcd_of_match[pdev->id].compatible)) {
+			dev_dbg(&pdev->dev, "fail to request vbus gpio [%d]\n", vbus_otg_en_gpio[pdev->id][0]);
+			//return -3;
+		}
+		gpio_direction_output(vbus_otg_en_gpio[pdev->id][0], 1);
+	}
+	
+	pr_info("vbus_otg_en_gpio:%d\n",vbus_otg_en_gpio[pdev->id][0]);
+	
+	aotg_power_onoff(pdev->id,1);
+
+	return 0;
+};
+
+static int aotg_hub_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;	//, *res_irq;
+	struct aotg_hcd *acthcd;
+	int irq;
+	int retval;
+
+	if (aotg_platform_device_init(pdev) <0) {
+		retval = -ENODEV;
+		goto err0;
+	}
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_mem) {
+		dev_err(&pdev->dev, "<HCD_PROBE>usb has no resource for mem!\n");
+		retval = -ENODEV;
+		goto err0;
+	}
+	printk("res_mem->start--end = 0x%x--0x%x\n",res_mem->start,res_mem->end);
+
+	hcd = usb_create_hcd(&act_hc_driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "<HCD_PROBE>usb create hcd failed\n");
+		retval = -ENOMEM;
+		goto err0;
+	}
+
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = res_mem->end - res_mem->start + 1;
+	
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(&pdev->dev, "<HCD_PROBE>usb has no resource for irq!\n");
+		retval = -ENODEV;
+		goto err1;
+	}
+	printk("irq = %d\n",irq);
+
+	if (!request_mem_region(res_mem->start, res_mem->end - res_mem->start + 1, dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "<HCD_PROBE>request_mem_region failed\n");
+		retval = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(res_mem->start, res_mem->end - res_mem->start + 1);
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "<HCD_PROBE>ioremap failed\n");
+		retval = -ENOMEM;
+		goto err2;
+	}
+	
+	retval = aotg_hcd_init(hcd, pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "<HCD_PROBE>hcd init failed\n");
+		goto err3;
+	}
+
+	acthcd = hcd_to_aotg(hcd);
+	act_hcd_ptr[pdev->id] = acthcd;
+	acthcd->dev = &pdev->dev;
+	acthcd->base = hcd->regs;
+	acthcd->hcd_exiting = 0;
+	acthcd->uhc_irq = irq;
+	acthcd->id = pdev->id;
+	dev_info(&pdev->dev, "pdev->id probe:%d\n", pdev->id);
+
+	aotg_hcd_hardware_init(acthcd);
+#if 0    
+#ifdef	CONFIG_PM
+	aotg_hcd_register_earlysuspend(acthcd);
+#endif
+#endif
+	//pdev->dev.dma_mask = NULL;
+
+	hcd->self.sg_tablesize = 32;
+//	hcd->self.sg_tablesize = ~0;
+
+	hcd->has_tt = 1;
+	hcd->self.uses_pio_for_control = 1;	/* for ep0, using CPU mode only. */
+
+	init_timer(&acthcd->hotplug_timer);
+	acthcd->hotplug_timer.function = aotg_hub_hotplug_timer;
+	acthcd->hotplug_timer.data = (unsigned long)acthcd;
+
+	init_timer(&acthcd->trans_wait_timer);
+	acthcd->trans_wait_timer.function = aotg_hub_trans_wait_timer;
+	acthcd->trans_wait_timer.data = (unsigned long)acthcd;
+	init_timer(&acthcd->check_trb_timer);
+	acthcd->check_trb_timer.function = aotg_check_trb_timer;
+	acthcd->check_trb_timer.data = (unsigned long)acthcd;
+	
+	retval = usb_add_hcd(hcd, irq, 0);
+	if (likely(retval == 0)) {
+		aotg_enable_irq(acthcd);
+		create_debug_file(acthcd);
+		dev_info(&pdev->dev, "hcd controller initialized. OTGIRQ: 0x%02X, OTGSTATE: 0x%02X \n", 
+				readb(acthcd->base + OTGIRQ),
+				readb(acthcd->base + OTGSTATE));
+
+		writeb(readb(acthcd->base + USBEIRQ), acthcd->base + USBEIRQ);
+		printk("USBEIRQ(0x%p): 0x%02X\n", acthcd->base + USBEIRQ, readb(acthcd->base + USBEIRQ));
+
+		// if (readb(acthcd->base + OTGSTATE) == AOTG_STATE_A_HOST) {
+			// acthcd->put_aout_msg = 0;
+			// mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(3));
+		// } else {
+			// acthcd->put_aout_msg = 1;
+			// mod_timer(&acthcd->hotplug_timer, jiffies + msecs_to_jiffies(1000));
+		// }
+
+		return 0;
+	} else {
+		dev_err(acthcd->dev, "<HCD_PROBE>usb add hcd failed\n");
+	}
+	
+	del_timer_sync(&acthcd->hotplug_timer);
+	del_timer_sync(&acthcd->trans_wait_timer);
+	del_timer_sync(&acthcd->check_trb_timer);
+err3:
+	if (acthcd != NULL) {
+		aotg_hcd_clk_enable(acthcd, 0);
+		iounmap(hcd->regs);
+	}
+err2:
+	release_mem_region(res_mem->start, res_mem->end - res_mem->start + 1);
+err1:
+	usb_put_hcd(hcd);
+err0:
+	dev_err(&pdev->dev, "%s: usb probe hcd  failed, error is %d", __func__, retval);
+
+	return retval;
+}
+
+#if 0
+static int inline aotg_hcd_stop_q(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	struct aotg_queue *q = NULL;
+	int ret = 0;
+
+	if ((!ep) || (!ep->q)) {
+		return 0;
+	}
+	q = ep->q;
+	if (list_empty(&q->finished_list)) {
+		q->status = -EIO;
+		ret = 1;
+		list_add_tail(&q->finished_list, &acthcd->hcd_finished_list);
+	} else {
+		return 0;
+	}
+
+	q->is_xfer_start = 0;
+
+	return ret;
+}
+
+static int aotg_hcd_flush_queue(struct aotg_hcd *acthcd)
+{
+	//struct usb_hcd *hcd = aotg_to_hcd(acthcd);
+	struct aotg_queue *q = NULL, *next;
+	struct urb *urb;
+	struct aotg_hcep *ep;
+	int i, ret = 0;
+
+	/* make sure all urb request is exited. */
+	//ep = acthcd->ep0;
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->ep0[i];
+		ret |= aotg_hcd_stop_q(acthcd, ep);
+	}
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->inep[i];
+		ret |= aotg_hcd_stop_q(acthcd, ep);
+	}
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->outep[i];
+		ret |= aotg_hcd_stop_q(acthcd, ep);
+	}
+
+	list_for_each_entry_safe(q, next, &acthcd->hcd_enqueue_list, enqueue_list) {
+		urb = q->urb;
+		ep = q->ep;
+		if (ep)
+			ep->urb_unlinked_cnt++;
+		if (q->enqueue_list.next != LIST_POISON1) {
+			list_del(&q->enqueue_list);
+			q->status = -EIO;
+			if (list_empty(&q->finished_list)) {
+				ret = 1;
+				list_add_tail(&q->finished_list, &acthcd->hcd_finished_list);
+			} else {
+				ACT_HCD_ERR
+			}
+		} else {
+			ACT_HCD_DBG
+		}
+	}
+
+	return ret;
+}
+#endif
+
+static int aotg_hub_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	struct aotg_hcep *ep;
+	int i;
+
+	usb_remove_hcd(hcd);
+	act_hcd_ptr[pdev->id] = NULL;
+#if 0    
+#ifdef CONFIG_PM
+	aotg_hcd_unregister_earlysuspend(acthcd);
+#endif
+#endif
+	aotg_disable_irq(acthcd);
+	aotg_hcd_clk_enable(acthcd, 0);
+	acthcd->hcd_exiting = 1;
+
+	tasklet_kill(&acthcd->urb_tasklet);
+	del_timer_sync(&acthcd->trans_wait_timer);
+	del_timer_sync(&acthcd->check_trb_timer);
+	del_timer_sync(&acthcd->hotplug_timer);
+	remove_debug_file(acthcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	//aotg_hcd_release_queue(acthcd, NULL);
+	owl_powergate_power_off(acthcd->id == 0 ? OWL_POWERGATE_USB2_0 : OWL_POWERGATE_USB2_1);
+
+	for (i = 0; i < MAX_EP_NUM; i++) {
+		ep = acthcd->ep0[i];
+		if (ep) {
+			ACT_HCD_DBG
+			if (ep->q)
+				ACT_HCD_DBG
+			kfree(ep);
+		}
+	}
+//fix here in 64 bit
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->inep[i];
+		if (ep) {
+			ACT_HCD_DBG
+			if (ep->ring) {
+				ACT_HCD_DBG
+				//aotg_free_ring(acthcd, ep->ring);
+			}
+			kfree(ep);
+		}
+	}
+	for (i = 1; i < MAX_EP_NUM; i++) {
+		ep = acthcd->outep[i];
+		if (ep) {
+			ACT_HCD_DBG
+			if (ep->ring) {
+				ACT_HCD_DBG
+				//aotg_free_ring(acthcd,ep->ring);
+			}
+			kfree(ep);
+		}
+	}
+	
+	usb_put_hcd(hcd);
+	printk("pdev->id remove:%d\n", pdev->id);
+	
+	if (!port_host_plug_detect[acthcd->id])
+		aotg_power_onoff(pdev->id,0);
+
+	return 0;
+}
+
+#ifdef	CONFIG_PM
+static int aotg_hcd_hub_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+
+	if ((hcd == NULL) || (acthcd == NULL)) {
+		ACT_HCD_ERR
+		return 0;
+	}
+	dev_info(acthcd->dev, " ==> %s\n", __func__);
+	/*do {
+		i++;
+		msleep(1);
+	} while ((acthcd->suspend_request_pend != 0) && (i < 200));*/
+
+	aotg_disable_irq(acthcd);
+	//usb_clearbitsb(OTGCTRL_BUSREQ, acthcd->base + OTGCTRL);
+	owl_powergate_power_off(acthcd->id == 0 ?
+		OWL_POWERGATE_USB2_0 : OWL_POWERGATE_USB2_1);
+	aotg_hcd_clk_enable(acthcd, 0);
+
+	aotg_power_onoff(pdev->id,0);
+	acthcd->lr_flag = 1;
+	return 0;
+}
+
+static int aotg_hcd_hub_resume(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct aotg_hcd *acthcd = hcd_to_aotg(hcd);
+	struct usb_device *udev;
+	int i;
+	
+	if ((hcd == NULL) || (acthcd == NULL)) {
+		ACT_HCD_ERR
+		return 0;
+	}
+
+	/* power on. */
+/*	if (acthcd->id == 0) {
+		aotg0_device_init(1);
+	} else {
+		aotg1_device_init(1);
+	}*/
+	//gpio_set_value_cansleep(vbus_otg_en_gpio[pdev->id][0], 1);
+	aotg_power_onoff(pdev->id,1);
+	msleep(10);
+
+	dev_info(acthcd->dev, " ==> %s\n", __func__);
+	aotg_hcd_hardware_init(acthcd);
+
+	//INIT_LIST_HEAD(&acthcd->hcd_enqueue_list);
+	
+	for (i = 0; i < MAX_EP_NUM; i++) {
+			if (acthcd->ep0[i] != NULL) {
+				break;
+			}
+		}
+	
+	if (i == MAX_EP_NUM) {
+		printk(KERN_ERR"%s, usb device is NULL!\n", __FUNCTION__);
+	}
+	else {
+		udev = acthcd->ep0[i]->udev;
+		//if (port_plug_en[acthcd->id]) {
+			usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+		//}	else {
+		//	usb_set_device_state(udev, USB_STATE_CONFIGURED);
+		//}
+	}
+	if (port_host_plug_detect[acthcd->id]) {
+		aotg_dev_plugout_msg(acthcd->id);
+	} else {
+		aotg_enable_irq(acthcd);
+	}
+	return 0;
+}
+#endif
+
+void aotg_hcd_shutdown(struct platform_device *pdev)
+{	
+	struct usb_hcd *hcd	= platform_get_drvdata(pdev);
+	struct aotg_hcd	*acthcd	= hcd_to_aotg(hcd);
+	printk("usb2-%d shutdown\n", acthcd->id);
+	
+	//gpio_set_value_cansleep(vbus_otg_en_gpio[pdev->id][0], 0);
+	aotg_power_onoff(pdev->id,0);
+	return;
+}
+
+static struct platform_driver aotg_hcd_hub_driver = {
+	.probe = aotg_hub_probe,
+	.remove = aotg_hub_remove,
+#ifdef	CONFIG_PM
+	.suspend = aotg_hcd_hub_suspend,
+	.resume = aotg_hcd_hub_resume,
+#endif
+	.shutdown = aotg_hcd_shutdown,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = platform_drv_name,
+		.of_match_table = aotg_hcd_of_match,
+	},
+};
+
+static inline int aotg_device_calc_id(int dev_id)
+{
+	int id;
+
+	if (hcd_ports_en_ctrl == 1) {
+		id = 0;
+	} else if (hcd_ports_en_ctrl == 2) {
+		id = 1;
+	} else if (hcd_ports_en_ctrl == 3) {
+		if (dev_id) {
+			id = 0;
+		} else {
+			id = 1;
+		}
+	} else {
+		id = dev_id;
+	}
+	return id;
+}
+
+int aotg_device_init(int dev_id)
+{
+	struct device_node *of_node;
+	struct resource res[2];
+	int ret = 0;
+	
+	mutex_lock(&aotg_onoff_mutex);
+	if (aotg_initialized[dev_id]) {
+		aotg_initialized[dev_id]++;
+		printk("aotg%d initialized allready! cnt:%d\n", dev_id, aotg_initialized[dev_id]);
+		mutex_unlock(&aotg_onoff_mutex);
+		return 0;
+	}
+	aotg_initialized[dev_id] = 1;
+	of_node = of_find_compatible_node(NULL, NULL, aotg_hcd_of_match[dev_id].compatible);
+	if (NULL == of_node) {
+		ERR("can't find usbh%d dts node\n",dev_id);
+		ret = -1;
+		goto err1;
+	}
+	
+	memset(&res, 0, sizeof(res));
+	if (of_address_to_resource(of_node, 0, &res[0])) {
+		ERR("can't fetch mem info from dts\n");
+		ret = -2;
+		goto err1;
+	}
+	
+	if (of_irq_to_resource(of_node, 0, &res[1]) == NO_IRQ) {
+		ERR("can't fetch IRQ info from dts\n");
+		ret = -3;
+		goto err1;
+	}
+	
+	aotg_dev[dev_id] = platform_device_alloc("aotg_hcd", dev_id);
+	if (!aotg_dev[dev_id]) {
+		ERR("platform_device_alloc fail\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+	aotg_dev[dev_id]->dev.dma_mask = &hcd_dmamask;
+	aotg_dev[dev_id]->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	
+	ret = platform_device_add_resources(aotg_dev[dev_id], res, ARRAY_SIZE(res));
+	if (ret) {
+		ERR("platform_device_add_resources fail\n");
+		goto err;
+	}
+
+	ret = platform_device_add_data(aotg_dev[dev_id], aotg_hcd_of_match[dev_id].data, sizeof(struct aotg_plat_data));
+	if (ret) {
+		ERR("platform_device_add_data fail\n");
+		goto err;
+	}
+
+	ret = platform_device_add(aotg_dev[dev_id]);
+	if (ret) {
+		ERR("platform_device_add fail\n");
+		goto err;
+	}
+	
+	mutex_unlock(&aotg_onoff_mutex);
+	return 0; 
+err:
+	platform_device_put(aotg_dev[dev_id]);
+	aotg_dev[dev_id] = NULL;
+err1:
+	mutex_unlock(&aotg_onoff_mutex);
+	return ret; 
+}
+
+void aotg_device_exit(int dev_id)
+{
+	mutex_lock(&aotg_onoff_mutex);
+	if (!aotg_initialized[dev_id]) {
+		printk("aotg%d exit allready!\n",dev_id);
+		mutex_unlock(&aotg_onoff_mutex);
+		return;
+	}
+	
+	aotg_initialized[dev_id]--;
+	if (aotg_initialized[dev_id] > 0) {
+		printk("aotg%d_exit cnt:%d\n", dev_id, aotg_initialized[dev_id]);
+		mutex_unlock(&aotg_onoff_mutex);
+		return;
+	}
+	aotg_initialized[dev_id] = 0;
+	
+	if (aotg_dev[dev_id] != NULL) {
+		platform_device_unregister(aotg_dev[dev_id]);
+		aotg_dev[dev_id] = NULL;
+	}
+	mutex_unlock(&aotg_onoff_mutex);
+}
+
+int aotg_hub_register(int dev_id)
+{
+	int proc_id;
+	proc_id = aotg_device_calc_id(dev_id);
+
+	//wake_lock(&acts_hcd_wakelock);
+
+//	if (dev_id) {
+//		proc_id = 1;
+		
+	/*if (!(aotg_registered_map&(1<<proc_id))) {
+		printk("register aotg_hcd%d device !\n", proc_id);
+		aotg_registered_map |= 1<<proc_id;
+		return aotg_device_init(proc_id);
+	}
+	else
+	{
+		ERR("aotg_hub%d device had been registered!\n",proc_id);
+	}*/
+	return aotg_device_init(proc_id);
+}
+EXPORT_SYMBOL(aotg_hub_register);
+
+void aotg_hub_unregister(int dev_id)
+{
+	int proc_id;
+	proc_id = aotg_device_calc_id(dev_id);
+	
+	/*if (aotg_registered_map&(1<<proc_id)) {
+		printk("unregister aotg_hcd%d device!\n", proc_id);
+		aotg_registered_map &= ~(1<<proc_id);
+		aotg_device_exit(dev_id);	
+	}
+	else
+	{
+		ERR("aotg_hcd%d device had been unregistered!\n",proc_id);
+	}*/
+	aotg_device_exit(dev_id);	
+}
+EXPORT_SYMBOL(aotg_hub_unregister);
+
+static int __init ahcd_init(void)
+{
+	mutex_init(&aotg_onoff_mutex);
+	platform_driver_register(&aotg_hcd_hub_driver);
+	//wake_lock_init(&acts_hcd_wakelock, WAKE_LOCK_SUSPEND, "acts_hcd");
+	create_acts_hcd_proc();
+	aotg_uhost_mon_init();
+	return 0;	
+}
+
+static void __exit ahcd_exit(void)
+{
+	remove_acts_hcd_proc();
+	platform_driver_unregister(&aotg_hcd_hub_driver);	
+	//wake_lock_destroy(&acts_hcd_wakelock);
+	aotg_uhost_mon_exit();
+	return;
+}
+
+module_init(ahcd_init);
+module_exit(ahcd_exit);
+
+MODULE_DESCRIPTION("Actions HCD controller driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/host/aotg_hcd.h b/drivers/usb/host/aotg_hcd.h
new file mode 100644
index 0000000..e169edd
--- /dev/null
+++ b/drivers/usb/host/aotg_hcd.h
@@ -0,0 +1,467 @@
+#ifndef  __LINUX_USB_HOST_AOTG_H 
+#define  __LINUX_USB_HOST_AOTG_H 
+
+#include <mach/hardware.h>
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/hcd.h>
+#include <linux/earlysuspend.h>
+
+#include "aotg_regs.h"
+
+//#define USBH_DEBUG
+
+#define	PERIODIC_SIZE		64 
+#define MAX_PERIODIC_LOAD	500 //50%
+
+#define  AOTG_BULK_FIFO_START_ADDR	0x0080
+#define  AOTG_INTERRUPT_FIFO_START_ADDR		0xC00    //max 1k
+
+ 
+#define  USB_HCD_IN_MASK	0x00 
+#define  USB_HCD_OUT_MASK 0x10 
+ 
+#define  AOTG_MAX_FIFO_SIZE    (512*10 + 64*2)	//5k
+#define  ALLOC_FIFO_UNIT        64
+//#define  AOTG_MIN_DMA_SIZE	  512
+//#define  AOTG_MIN_DMA_SIZE	  64
+#define  AOTG_MIN_DMA_SIZE	  0
+ 
+#define AOTG_PORT_C_MASK  ((USB_PORT_STAT_C_CONNECTION \
+	| USB_PORT_STAT_C_ENABLE \
+	| USB_PORT_STAT_C_SUSPEND \
+	| USB_PORT_STAT_C_OVERCURRENT \
+	| USB_PORT_STAT_C_RESET) << 16) 
+
+#define MAX_EP_NUM		16   //count of each type, 1st is reserved
+#define MAX_SG_TABLE	(0x1 << 9)
+
+#define MAX_ERROR_COUNT	6
+
+#ifndef USBH0_ECS
+#define USBH0_ECS  (TIMER_2HZ_BASE+0x0084)
+#endif
+
+#define CMU_USBPLL_USBPLL0EN	0x1500
+
+#define CMU_DEVRST1_USBH0	0x01
+
+#define CMU_USBPLL_USBPLL1EN	0x2a00
+
+#define CMU_DEVRST1_USB1	(1<<22)
+
+#ifndef USBH1_ECS
+#define USBH1_ECS  (TIMER_2HZ_BASE+0x0088)
+#endif
+
+/* 0 is all enable, 1 -- just usb0 enable, 2 -- usb1 enable, 
+ * 3 -- usb0 and usb1 enable,but reversed. 
+ */
+extern int hcd_ports_en_ctrl;
+
+extern struct aotg_hcd *act_hcd_ptr[2];
+
+struct hcd_stats { 
+	unsigned long  insrmv; 
+	unsigned long  wake; 
+	unsigned long sof; 
+}; 
+ 
+enum aotg_rh_state { 
+	AOTG_RH_POWEROFF, 
+	AOTG_RH_POWERED, 
+	AOTG_RH_ATTACHED, 
+	AOTG_RH_NOATTACHED, 
+	AOTG_RH_RESET, 
+	AOTG_RH_ENABLE, 
+	AOTG_RH_DISABLE, 
+	AOTG_RH_SUSPEND, 
+	AOTG_RH_ERR 
+}; 
+
+enum control_phase {
+	PHASE_UNDEFINED,
+	PHASE_SETUP,
+	PHASE_DATA,
+	PHASE_STATUS,
+};
+
+#define TRB_ITE	(1 << 11)
+#define TRB_CHN	(1 << 10)
+#define TRB_CSP	(1 << 9)
+#define TRB_COF	(1 << 8)
+#define TRB_ICE	(1 << 7)
+#define TRB_IZE	(1 << 6)
+#define TRB_ISE (1 << 5)
+#define TRB_LT	(1 << 4)
+#define AOTG_TRB_IOC	(1 << 3)
+#define AOTG_TRB_IOZ	(1 << 2)
+#define AOTG_TRB_IOS	(1 << 1)
+#define TRB_OF	(1 << 0)
+
+struct aotg_trb {
+	u32 hw_buf_ptr;
+	u32 hw_buf_len;
+	u32 hw_buf_remain;
+	u32 hw_token;
+};
+
+#define USE_SG
+#ifdef USE_SG
+#define NUM_TRBS (256)
+#define RING_SIZE (NUM_TRBS * 16)
+#else
+#define NUM_TRBS (64)
+#define RING_SIZE (NUM_TRBS * 16)
+#endif
+
+//#define INTR_TRBS (256)
+#define INTR_TRBS (10)
+
+
+#define RING_IN_OF (0xFFFE)
+#define RING_OUT_OF (0xFFFE0000)
+
+#define TD_IN_FINISH (0) 
+#define TD_IN_RING  (0x1 << 0)
+#define TD_IN_QUEUE (0x1 << 1)
+
+struct aotg_ring {
+	//need a protect lock
+	unsigned is_running:1;
+	unsigned is_out:1;
+	unsigned intr_inited:1;
+	unsigned intr_started:1;
+	unsigned ring_stopped:1;
+	int num_trbs;
+	//int irq_interval;
+	//int td_irq_interval;
+	int type;
+	u8 mask;
+	void *priv;
+	atomic_t num_trbs_free;
+
+	int intr_mem_size;
+	struct dma_pool *intr_dma_pool;
+	u8 *intr_dma_buf_vaddr;
+	dma_addr_t intr_dma_buf_phyaddr;
+	char pool_name[32];
+	
+	struct aotg_trb *enqueue_trb;
+	struct aotg_trb *dequeue_trb;
+	struct aotg_trb *first_trb;
+	struct aotg_trb *last_trb;
+	struct aotg_trb *ring_trb;
+	u32 trb_dma;
+
+	unsigned int enring_cnt;
+	unsigned int dering_cnt;
+
+	volatile void __iomem *reg_dmalinkaddr;
+	volatile void __iomem *reg_curaddr;
+	volatile void __iomem *reg_dmactrl;
+	volatile void __iomem *reg_dmacomplete_cnt;
+};
+
+struct aotg_td {
+	struct urb *urb;
+	int num_trbs; 
+	u32 trb_dma;	
+	int err_count;
+	struct aotg_trb *trb_vaddr;
+
+	struct list_head queue_list;
+	struct list_head enring_list;
+	struct list_head dering_list;
+
+	u8 *intr_mem_vaddr;
+	dma_addr_t intr_men_phyaddr;
+	int mem_size;
+
+	unsigned cross_ring:1;
+};
+
+struct aotg_queue {
+	int in_using;
+	struct aotg_hcep *ep;
+	struct urb *urb;
+	int dma_no;
+	int is_xfer_start;
+	int need_zero;
+
+	//struct list_head dma_q_list;
+	//struct list_head ep_q_list;
+	struct list_head enqueue_list;
+	struct list_head dequeue_list;
+	struct list_head finished_list;
+	int status;	//for dequeue
+	int length;
+
+	struct aotg_td td;
+
+	struct scatterlist *cur_sg;
+	int err_count;
+	unsigned long timeout;	/* jiffies + n. */
+
+	/* fixing dma address unaligned to 4 Bytes. */
+	u8 * dma_copy_buf;
+	dma_addr_t dma_addr;	
+
+	/* for debug. */
+	unsigned int seq_info;
+} __attribute__ ((aligned (4)));
+
+struct aotg_dma_buf { 
+	unsigned int size;
+	u8 * buf;
+	dma_addr_t dma;	
+	int in_using;
+};
+
+struct aotg_hcd { 
+	int	id;
+	spinlock_t lock;
+	spinlock_t tasklet_lock;
+	int check_trb_mutex;
+	volatile int tasklet_retry;
+	void __iomem *base;
+	struct device *dev;
+	struct aotg_plat_data  *port_specific;
+	struct proc_dir_entry *pde; 
+	enum   usb_device_speed  speed; 
+	int    inserted;	/*imply a USB deivce inserting in MiniA receptacle*/ 
+	u32 port;		/*indicate portstatus and portchange*/
+	enum aotg_rh_state  rhstate;
+
+	int hcd_exiting;
+
+	u16 hcin_dma_ien;
+	u16 hcout_dma_ien;
+	
+	/* when using hub, every usb device need a ep0 hcep data struct, but share the same hcd ep0. */
+	struct aotg_hcep    *active_ep0;
+	int ep0_block_cnt;
+	struct aotg_hcep    *ep0[MAX_EP_NUM];
+	struct aotg_hcep	*inep[MAX_EP_NUM];   // 0 for reserved
+	struct aotg_hcep	*outep[MAX_EP_NUM];  // 0 for reserved
+
+	struct list_head hcd_enqueue_list;
+	struct list_head hcd_dequeue_list;
+	struct list_head hcd_finished_list;
+	struct tasklet_struct urb_tasklet;
+
+	struct timer_list hotplug_timer;
+	struct timer_list check_trb_timer;
+	struct timer_list trans_wait_timer;
+	ulong fifo_map[AOTG_MAX_FIFO_SIZE/ALLOC_FIFO_UNIT];
+
+	int discon_happened;
+	int put_aout_msg;
+	int suspend_request_pend;
+	int uhc_irq;
+	
+#ifdef CONFIG_PM	
+#define USB_RESET_DEVICE (0)
+#define USB_RESET_AND_VERIFY_DEVICE	(1)
+	int lr_flag;
+  struct early_suspend earlysuspend;
+
+#	endif
+
+	#define AOTG_QUEUE_POOL_CNT	60
+	struct aotg_queue *queue_pool[AOTG_QUEUE_POOL_CNT];
+	#define AOTG_DMA_BUF_CNT	8
+	struct aotg_dma_buf dma_poll[AOTG_DMA_BUF_CNT];
+}; 
+ 
+struct aotg_hcep { 
+	struct usb_host_endpoint *hep; 
+	struct usb_device *udev; 
+	int index;
+	/* just for ep0, when using hub, every usb device need a ep0 hcep data struct, but share the same hcd ep0. */
+	int ep0_index;
+	int iso_packets;
+	u32 maxpacket; 
+	u16 error_count; 
+	u16 length;
+	u8 epnum; 
+	u8 nextpid; 
+	u8 mask; 
+	u8 type;
+	u8 is_out;
+	u8 buftype; 
+	u8 has_hub; 
+	u8 hub_addr; 
+	u8 reg_hcep_splitcs_val; 
+
+	void __iomem *reg_hcepcs; 
+	void __iomem *reg_hcepcon; 
+   	void __iomem *reg_hcepctrl; 
+	void __iomem *reg_hcepbc; 
+	void __iomem *reg_hcmaxpck; 
+	void __iomem *reg_hcepaddr; 
+	void __iomem *reg_hcerr;
+	//void __iomem *reg_hcfifo; 
+	void __iomem *reg_hcep_interval;
+	void __iomem *reg_hcep_dev_addr; 
+	void __iomem *reg_hcep_port; 
+	void __iomem *reg_hcep_splitcs; 
+
+	unsigned int urb_enque_cnt; 
+	unsigned int urb_endque_cnt; 
+	unsigned int urb_stop_stran_cnt; 
+	unsigned int urb_unlinked_cnt; 
+
+	u32 dma_bytes;
+	u16 interval; 
+	u16 load; 	/* one packet times in us. */
+
+	//u16 branch; 
+	//struct aotg_hcep *next; 
+	u16 fifo_busy;
+
+	ulong fifo_addr;
+	struct aotg_queue *q;
+
+	struct aotg_ring *ring;
+	struct list_head queue_td_list;
+	struct list_head enring_td_list;
+	struct list_head dering_td_list;
+	
+}; 
+
+#define  get_hcepcon_reg(dir , x , y , z)   ((dir ? x : y) + (z - 1)*8)
+#define  get_hcepcs_reg(dir , x , y , z)   ((dir ? x : y) + (z - 1)*8)
+#define  get_hcepctrl_reg(dir , x , y , z)   ((dir ? x : y) + (z - 1)*4)
+#define  get_hcepbc_reg(dir , x , y , z)   ((dir ? x : y) + (z - 1)*8)
+#define  get_hcepmaxpck_reg(dir , x , y , z)   ((dir ? x : y) + (z - 1)*2)
+#define  get_hcepaddr_reg(dir , x , y , z)  ((dir ? x : y) + (z - 1)*4)
+//#define  get_hcfifo_reg(x , z)   (x + (z - 1)*4)
+#define  get_hcep_dev_addr_reg(dir , x , y , z)  ((dir ? x : y) + (z - 1)*8)
+#define  get_hcep_port_reg(dir , x , y , z)  ((dir ? x : y) + (z - 1)*8)
+#define  get_hcep_splitcs_reg(dir , x , y , z)  ((dir ? x : y) + (z - 1)*8)
+
+#define AOTG_DMA_OUT_PREFIX		0x10
+#define AOTG_DMA_NUM_MASK		0xf
+#define AOTG_IS_DMA_OUT(x)		((x) & AOTG_DMA_OUT_PREFIX)
+#define AOTG_GET_DMA_NUM(x)		((x) & AOTG_DMA_NUM_MASK)
+
+#define GET_DMALINKADDR_REG(dir, x, y, z) ((dir ? x : y) + (z - 1) * 0x10)
+#define GET_CURADDR_REG(dir, x, y, z) ((dir ? x : y) + (z - 1) * 0x10)
+#define GET_DMACTRL_REG(dir, x, y, z) ((dir ? x : y) + (z - 1) * 0x10)
+#define GET_DMACOMPLETE_CNT_REG(dir, x, y, z) ((dir ? x : y) + (z - 1) * 0x10)
+
+
+static inline struct aotg_hcd *hcd_to_aotg(struct usb_hcd *hcd) 
+{ 
+	return (struct aotg_hcd *) (hcd->hcd_priv); 
+}
+
+static inline void aotg_clear_all_overflow_irq(struct aotg_hcd *acthcd)
+{
+	unsigned int irq_pend = 0; 
+	
+	irq_pend = readl(acthcd->base + HCDMAxOVERFLOWIRQ);
+	
+	if (irq_pend) {
+		writel(irq_pend, acthcd->base + HCDMAxOVERFLOWIRQ);		
+	}
+	return;
+}
+
+static inline void aotg_clear_all_shortpkt_irq(struct aotg_hcd *acthcd)
+{
+	unsigned int irq_pend = 0;
+
+	irq_pend = readw(acthcd->base + HCINxSHORTPCKIRQ0);
+
+	if (irq_pend) {
+		writew(irq_pend, acthcd->base + HCINxSHORTPCKIRQ0);
+	}
+	return;
+}
+
+static inline void aotg_clear_all_zeropkt_irq(struct aotg_hcd *acthcd)
+{
+	unsigned int irq_pend = 0;
+
+	irq_pend = readw(acthcd->base + HCINxZEROPCKIEN0);
+
+	if (irq_pend) {
+		writew(irq_pend, acthcd->base + HCINxZEROPCKIEN0);
+	}
+	return;
+}
+
+static inline void aotg_clear_all_hcoutdma_irq(struct aotg_hcd *acthcd)
+{
+	unsigned int irq_pend = 0;
+
+	irq_pend = readw(acthcd->base + HCOUTxDMAIRQ0);
+
+	if (irq_pend) {
+		writew(irq_pend, acthcd->base + HCOUTxDMAIRQ0);
+	}
+	return;
+}
+
+static inline void aotg_hcep_reset(struct aotg_hcd *acthcd, u8 ep_mask, u8 type_mask)
+{
+	u8 val;
+
+	writeb(ep_mask, acthcd->base + ENDPRST);	/*select ep */
+	val = ep_mask | type_mask;
+	writeb(val, acthcd->base + ENDPRST);	/*reset ep */
+	return;
+}
+ 
+static inline struct usb_hcd *aotg_to_hcd(struct aotg_hcd *acthcd) 
+{ 
+	return container_of((void *)acthcd, struct usb_hcd, hcd_priv); 
+}
+
+void aotg_hcd_dump_td(struct aotg_ring *ring, struct aotg_td *td);
+struct aotg_ring *aotg_alloc_ring(struct aotg_hcd *acthcd,
+				struct aotg_hcep *ep, unsigned int num_trbs, 
+				gfp_t mem_flags);
+void aotg_free_ring(struct aotg_hcd *acthcd, struct aotg_ring *ring);
+void enable_overflow_irq(struct aotg_hcd *acthcd, struct aotg_hcep *ep);
+
+void dequeue_td(struct aotg_ring *ring, struct aotg_td *td, int dequeue_flag);
+int aotg_ring_enqueue_td(struct aotg_hcd *acthcd, 
+				struct aotg_ring *ring, struct aotg_td *td);
+int aotg_ring_dequeue_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, 
+			struct aotg_td *td, int dequeue_flag);
+int aotg_ring_enqueue_isoc_td(struct aotg_hcd *acthcd, 
+				struct aotg_ring *ring, struct aotg_td *td);
+int aotg_ring_enqueue_intr_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, 
+							struct aotg_hcep *ep, struct urb *urb, gfp_t mem_flags);
+int aotg_ring_dequeue_intr_td(struct aotg_hcd *acthcd, struct aotg_hcep *ep,
+			struct aotg_ring *ring,	struct aotg_td *td);
+void aotg_intr_dma_pool_destroy(struct aotg_ring *ring);
+void aotg_intr_dma_buf_free(struct aotg_hcd *acthcd, struct aotg_ring *ring);
+
+struct aotg_td *aotg_alloc_td(gfp_t mem_flags);
+void aotg_release_td(struct aotg_td *td);
+
+int is_ring_running(struct aotg_ring *ring);
+void aotg_start_ring(struct aotg_ring *ring, u32 addr);
+void aotg_stop_ring(struct aotg_ring *ring);
+u32 ring_trb_virt_to_dma(struct aotg_ring *ring, 
+							struct aotg_trb *trb_vaddr);
+
+void aotg_ring_irq_handler(struct aotg_hcd *acthcd);
+
+void aotg_dump_linklist_reg_2(struct aotg_hcd *acthcd, int dmanr);
+
+int intr_finish_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, struct aotg_td *td);
+void dequeue_intr_td(struct aotg_ring *ring, struct aotg_td *td);
+void aotg_reorder_intr_td( struct aotg_hcep *ep);
+int aotg_intr_chg_buf_len(struct aotg_hcd *acthcd, struct aotg_ring *ring, int len);
+int aotg_intr_get_finish_trb(struct aotg_ring *ring);
+void aotg_reorder_iso_td(struct aotg_hcd *acthcd, struct aotg_ring *ring);
+void handle_ring_dma_tx(struct aotg_hcd *acthcd, unsigned int irq_mask);
+
+#endif /* __LINUX_USB_HOST_AOTG_H */ 
+ 
diff --git a/drivers/usb/host/aotg_mon.c b/drivers/usb/host/aotg_mon.c
new file mode 100644
index 0000000..6b3b16d
--- /dev/null
+++ b/drivers/usb/host/aotg_mon.c
@@ -0,0 +1,386 @@
+/*
+ * (C) Copyright www.actions-semi.com 2012-2014
+ *	   Written by houjingkun. <houjingkun at actions-semi.com>
+ * 
+ * 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; either	version	2 of the License, or (at your
+ * option) any later version.
+ *
+ * This	program	is distributed in the hope that	it will	be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A	PARTICULAR PURPOSE.	 See the GNU General Public	License
+ * for more	details.
+ *
+ * You should have received	a copy of the GNU General Public License
+ * along with this program;	if not,	write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139,	USA.
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/kthread.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/hcd.h>
+
+#include <asm/irq.h>
+#include <linux/regulator/consumer.h>
+#include <mach/hardware.h>
+#include <linux/clk.h>
+#include <linux/wakelock.h>
+#include <linux/suspend.h>
+#include <mach/debug.h>
+#include <asm/prom.h>
+#include <mach/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <mach/powergate.h>
+
+#include "aotg_hcd.h"
+#include "aotg_regs.h"
+#include "aotg_plat_data.h"
+#include "aotg_debug.h"
+
+int aotg_device_init(int dev_id);
+void aotg_device_exit(int dev_id);
+void aotg_power_onoff(int id,int on_off);
+
+
+/* usbecs register. */
+#define	USB2_ECS_VBUS_P0		10
+#define	USB2_ECS_ID_P0			12
+#define USB2_ECS_LS_P0_SHIFT	8
+#define USB2_ECS_LS_P0_MASK		(0x3<<8)
+#define USB2_ECS_DPPUEN_P0     3
+#define USB2_ECS_DMPUEN_P0     2
+#define USB2_ECS_SOFTIDEN_P0   26
+#define USB2_ECS_SOFTID_P0     27
+#define USB2_ECS_SOFTVBUSEN_P0 24
+#define USB2_ECS_SOFTVBUS_P0   25
+#define USB2_ECS_PLL_LDO_EN   (1<<7)
+#define USB2_PLL_EN0           (1<<12)
+#define USB2_PLL_EN1           (1<<13)
+#define USB2_PHYCLK_EN0           (1<<10)
+#define USB2_PHYCLK_EN1           (1<<11)
+
+struct aotg_uhost_mon_t {
+	int id;
+	void __iomem *usbecs;
+	void __iomem *usbpll;
+
+	struct timer_list hotplug_timer;
+
+	struct workqueue_struct *aotg_dev_onoff;
+	struct delayed_work aotg_dev_init;
+	struct delayed_work aotg_dev_exit; 
+	struct wake_lock aotg_wake_lock;
+
+	unsigned int aotg_uhost_det;
+
+	/* dp, dm state. */
+	unsigned int old_state;
+	unsigned int state;
+};
+
+int port_host_plug_detect[2] = {0};
+extern int is_ls_device[2];
+extern int vbus_otg_en_gpio[2][2];
+extern struct of_device_id aotg_hcd_of_match[];
+static struct aotg_uhost_mon_t * aotg_uhost_mon0 = NULL;
+static struct aotg_uhost_mon_t * aotg_uhost_mon1 = NULL;
+
+int usb2_set_dp_500k_15k(struct aotg_uhost_mon_t * umon, int enable_500k_up, int enable_15k_down)
+{
+	unsigned int val;
+	
+	val = readl(umon->usbecs) & (~((1 << USB2_ECS_DPPUEN_P0) |
+			(1 << USB2_ECS_DMPUEN_P0)));
+			
+	if (enable_500k_up != 0) {
+		val |= (1 << USB2_ECS_DPPUEN_P0)|(1 << USB2_ECS_DMPUEN_P0);
+	}
+	
+	writel(val, umon->usbecs);	/* 500k up enable, 15k down disable; */
+	return 0;		
+}
+
+/* return dp, dm state. */
+static inline unsigned int usb_get_linestates(struct aotg_uhost_mon_t * umon)
+{
+	unsigned int state;
+
+	state = ((readl(umon->usbecs) & USB2_ECS_LS_P0_MASK) >> USB2_ECS_LS_P0_SHIFT);
+	return state;
+}
+
+static void aotg_uhost_mon_timer(unsigned long data)
+{
+	static int cnt = 0;
+	struct aotg_uhost_mon_t * umon = (struct aotg_uhost_mon_t *)data;
+
+	if ((!umon) || (!umon->aotg_uhost_det)) {
+		return;
+	}
+	umon->state = usb_get_linestates(umon);
+
+	cnt++;
+	if ((cnt % 16) == 0) {
+	}
+
+	if (umon->state != 0) {
+		if ((umon->state == umon->old_state) && (umon->state != 0x3)) {
+			umon->aotg_uhost_det = 0;
+			umon->old_state = 0;
+			if(umon->state==2) 
+				is_ls_device[umon->id]=1;
+			queue_delayed_work(umon->aotg_dev_onoff, &umon->aotg_dev_init, msecs_to_jiffies(1));
+			return;
+		}
+	}
+
+	umon->old_state = umon->state;
+	mod_timer(&umon->hotplug_timer, jiffies + msecs_to_jiffies(500));
+	return;
+}
+
+static void aotg_dev_register(struct work_struct *w)
+{
+	struct aotg_uhost_mon_t *umon = container_of(w, struct aotg_uhost_mon_t, aotg_dev_init.work);
+
+	if (umon->id) {
+		usb_clearbitsl(USB2_PLL_EN1,aotg_uhost_mon1->usbpll);
+		owl_powergate_power_off(OWL_POWERGATE_USB2_1);
+	} else {
+		usb_clearbitsl(USB2_PLL_EN0,aotg_uhost_mon0->usbpll);
+		owl_powergate_power_off(OWL_POWERGATE_USB2_0);
+	}
+	wake_lock_timeout(&umon->aotg_wake_lock, 15*HZ);
+	aotg_device_init(umon->id);
+	return;
+}
+
+static void aotg_dev_unregister(struct work_struct *w)
+{
+	struct aotg_uhost_mon_t *umon = container_of(w, struct aotg_uhost_mon_t, aotg_dev_exit.work);
+
+	lock_system_sleep();
+	wake_lock_timeout(&umon->aotg_wake_lock, 15*HZ);
+	unlock_system_sleep();
+
+	aotg_device_exit(umon->id);
+	umon->aotg_uhost_det = 1;
+	if (umon->id) {
+		owl_powergate_power_on(OWL_POWERGATE_USB2_1);
+		usb_setbitsl(USB2_PLL_EN1,aotg_uhost_mon1->usbpll);
+		usb_setbitsl(USB2_PHYCLK_EN1,aotg_uhost_mon1->usbpll);
+		usb_setbitsl(USB2_ECS_PLL_LDO_EN,aotg_uhost_mon1->usbecs);
+		usb2_set_dp_500k_15k(aotg_uhost_mon1, 0, 1);        
+		is_ls_device[1]=0;
+	} else {
+		owl_powergate_power_on(OWL_POWERGATE_USB2_0);
+		usb_setbitsl(USB2_PLL_EN0,aotg_uhost_mon0->usbpll);
+		usb_setbitsl(USB2_PHYCLK_EN0,aotg_uhost_mon0->usbpll);
+		usb_setbitsl(USB2_ECS_PLL_LDO_EN,aotg_uhost_mon0->usbecs);
+		usb2_set_dp_500k_15k(aotg_uhost_mon0, 0, 1);        
+		is_ls_device[0]=0;
+	}
+	
+	mod_timer(&umon->hotplug_timer, jiffies + msecs_to_jiffies(1000));
+	return;
+}
+
+void aotg_dev_plugout_msg(int id)
+{
+	struct aotg_uhost_mon_t *umon = NULL;
+
+	printk("usb%d had been plugged out!\n",id);
+	if ((id == 0) && aotg_uhost_mon0) {
+		umon = aotg_uhost_mon0;
+	} else if ((id == 1) && aotg_uhost_mon1) {
+		umon = aotg_uhost_mon1;
+	} else {
+		ACT_HCD_DBG
+		return;
+	}
+
+	umon->old_state = 0;
+	queue_delayed_work(umon->aotg_dev_onoff, &umon->aotg_dev_exit, msecs_to_jiffies(1000));
+	return;
+}
+
+static struct aotg_uhost_mon_t * aotg_uhost_mon_alloc(void)
+{
+	struct aotg_uhost_mon_t *umon = NULL;
+
+	umon = kzalloc(sizeof(*umon), GFP_KERNEL);
+	if (!umon)
+		return NULL;
+
+	init_timer(&umon->hotplug_timer);
+	umon->hotplug_timer.function = aotg_uhost_mon_timer;
+	umon->hotplug_timer.data = (unsigned long)umon;
+
+	INIT_DELAYED_WORK(&umon->aotg_dev_init, aotg_dev_register);
+	INIT_DELAYED_WORK(&umon->aotg_dev_exit, aotg_dev_unregister);
+
+	umon->aotg_uhost_det = 1;
+
+	return umon;
+}
+
+void aotg_uhost_mon_init(void)
+{
+	struct device_node *of_node;
+	enum of_gpio_flags flags;
+	
+	of_node = of_find_compatible_node(NULL, NULL, "actions,owl-usb-2.0-0");
+	if (of_node) {
+		if (!of_find_property(of_node, "port0_host_plug_detect", NULL)) {
+			pr_info("can't find port0_host_plug_detect config\n");
+			port_host_plug_detect[0] = 0;
+		}	else {
+			port_host_plug_detect[0] = be32_to_cpup((const __be32 *)of_get_property(of_node,  "port0_host_plug_detect",NULL));
+		}
+		pr_info("port_host_plug_detect[0]:%d\n", port_host_plug_detect[0]);
+		
+		if (!of_find_property(of_node, "vbus_otg_en_gpio", NULL)) {
+			pr_debug("can't find vbus_otg0_en_gpio config\n");
+			vbus_otg_en_gpio[0][0] = -1;
+		}	else {
+			vbus_otg_en_gpio[0][0] = of_get_named_gpio_flags(of_node,  "vbus_otg_en_gpio",0, &flags);
+			vbus_otg_en_gpio[0][1] = flags & 0x01;
+			if (gpio_request(vbus_otg_en_gpio[0][0], aotg_hcd_of_match[0].compatible))
+				pr_debug("fail to request vbus gpio [%d]\n", vbus_otg_en_gpio[0][0]);
+			if (port_host_plug_detect[0] != 2)
+				gpio_direction_output(vbus_otg_en_gpio[0][0], !!port_host_plug_detect[0]);
+		}
+		pr_info("port0_vubs_en:%d\n",vbus_otg_en_gpio[0][0]);
+	}
+	else {
+		pr_debug("can't find usbh0 dts node\n");
+	}
+	
+	of_node = of_find_compatible_node(NULL, NULL, "actions,owl-usb-2.0-1");
+	if (of_node) {
+		if (!of_find_property(of_node, "port1_host_plug_detect", NULL)) {
+			pr_info("can't find port1_host_plug_detect config\n");
+			port_host_plug_detect[1] = 0;
+		}	else {
+			port_host_plug_detect[1] = be32_to_cpup((const __be32 *)of_get_property(of_node,  "port1_host_plug_detect",NULL));
+		}
+		pr_info("port_host_plug_detect[1]:%d\n", port_host_plug_detect[1]);
+		
+		if (!of_find_property(of_node, "vbus_otg_en_gpio", NULL)) {
+			printk("can't find vbus_otg1_en_gpio config\n");
+			vbus_otg_en_gpio[1][0] = -1;
+		}	else {
+			vbus_otg_en_gpio[1][0] = of_get_named_gpio_flags(of_node,  "vbus_otg_en_gpio",0, &flags);
+			vbus_otg_en_gpio[1][1] = flags & 0x01;
+			if (gpio_request(vbus_otg_en_gpio[1][0], aotg_hcd_of_match[1].compatible))
+				pr_debug("fail to request vbus gpio [%d]\n", vbus_otg_en_gpio[1][0]);
+			if (port_host_plug_detect[1] != 2)
+				gpio_direction_output(vbus_otg_en_gpio[1][0], !!port_host_plug_detect[1]);
+		}
+		pr_info("port1_vubs_en:%d\n",vbus_otg_en_gpio[1][0]);
+	}
+	else {
+		pr_debug("can't find usbh1 dts node\n");
+	}
+	
+	if (port_host_plug_detect[0]) {
+		aotg_uhost_mon0 = aotg_uhost_mon_alloc();
+		aotg_uhost_mon0->id = 0;
+		aotg_uhost_mon0->aotg_dev_onoff = create_singlethread_workqueue("aotg_dev0_onoff");
+		aotg_uhost_mon0->usbecs = (void __iomem *)IO_ADDRESS(USBH0_ECS);
+		aotg_uhost_mon0->usbpll = (void __iomem *)IO_ADDRESS(CMU_USBPLL);
+
+		owl_powergate_power_on(OWL_POWERGATE_USB2_0);
+		usb_setbitsl(USB2_PLL_EN0,aotg_uhost_mon0->usbpll);
+		usb_setbitsl(USB2_PHYCLK_EN0,aotg_uhost_mon0->usbpll);
+		usb_setbitsl(USB2_ECS_PLL_LDO_EN,aotg_uhost_mon0->usbecs);
+		usb2_set_dp_500k_15k(aotg_uhost_mon0, 0, 1);
+		wake_lock_init(&aotg_uhost_mon0->aotg_wake_lock, WAKE_LOCK_SUSPEND, "aotg_wake_lock0");
+		printk("start mon 0 ......\n");
+		mod_timer(&aotg_uhost_mon0->hotplug_timer, jiffies + msecs_to_jiffies(10000));
+	}
+	if (port_host_plug_detect[1]) {
+		aotg_uhost_mon1 = aotg_uhost_mon_alloc();
+		aotg_uhost_mon1->id = 1;
+		aotg_uhost_mon1->aotg_dev_onoff = create_singlethread_workqueue("aotg_dev1_onoff");
+		aotg_uhost_mon1->usbecs = (void __iomem *)IO_ADDRESS(USBH1_ECS);
+		aotg_uhost_mon1->usbpll = (void __iomem *)IO_ADDRESS(CMU_USBPLL);
+
+		owl_powergate_power_on(OWL_POWERGATE_USB2_1);
+		usb_setbitsl(USB2_PLL_EN1,aotg_uhost_mon1->usbpll);
+		usb_setbitsl(USB2_PHYCLK_EN1,aotg_uhost_mon1->usbpll);
+		usb_setbitsl(USB2_ECS_PLL_LDO_EN,aotg_uhost_mon1->usbecs);
+		usb2_set_dp_500k_15k(aotg_uhost_mon1, 0, 1);
+		wake_lock_init(&aotg_uhost_mon1->aotg_wake_lock, WAKE_LOCK_SUSPEND, "aotg_wake_lock1");
+		printk("start mon 1 ......\n");
+		mod_timer(&aotg_uhost_mon1->hotplug_timer, jiffies + msecs_to_jiffies(10000));
+	}
+
+	return;
+}
+
+static int inline aotg_uhost_mon_free(struct aotg_uhost_mon_t *umon)
+{
+	if (!umon)
+		return -1;
+
+	if (umon->id) {
+		usb_clearbitsl(USB2_PLL_EN1,aotg_uhost_mon1->usbpll);
+		owl_powergate_power_off(OWL_POWERGATE_USB2_1);
+	} else {
+		usb_clearbitsl(USB2_PLL_EN0,aotg_uhost_mon0->usbpll);
+		owl_powergate_power_off(OWL_POWERGATE_USB2_0);
+	}
+	
+	if (umon->aotg_dev_onoff) {
+		cancel_delayed_work_sync(&umon->aotg_dev_init);
+		cancel_delayed_work_sync(&umon->aotg_dev_exit);
+		flush_workqueue(umon->aotg_dev_onoff);
+		destroy_workqueue(umon->aotg_dev_onoff);
+	}
+	wake_unlock(&umon->aotg_wake_lock);
+	del_timer_sync(&umon->hotplug_timer);
+	kfree(umon);
+	return 0;
+}
+
+void aotg_uhost_mon_exit(void)
+{
+	aotg_power_onoff(0,0);
+	aotg_power_onoff(1,0);
+
+	aotg_uhost_mon_free(aotg_uhost_mon0);
+	aotg_uhost_mon_free(aotg_uhost_mon1);
+	aotg_uhost_mon0 = NULL;
+	aotg_uhost_mon1 = NULL;
+	return;
+}
+
+
diff --git a/drivers/usb/host/aotg_mon.h b/drivers/usb/host/aotg_mon.h
new file mode 100644
index 0000000..37e9a69c
--- /dev/null
+++ b/drivers/usb/host/aotg_mon.h
@@ -0,0 +1,11 @@
+#ifndef __AOTG_UHOST_MON_H__
+#define __AOTG_UHOST_MON_H__
+
+void aotg_dev_plugout_msg(int id);
+extern int port_host_plug_detect[2];
+
+void aotg_uhost_mon_init(void);
+void aotg_uhost_mon_exit(void);
+
+#endif /* __AOTG_UHOST_MON_H__ */
+
diff --git a/drivers/usb/host/aotg_plat_data.h b/drivers/usb/host/aotg_plat_data.h
new file mode 100644
index 0000000..26e36c6
--- /dev/null
+++ b/drivers/usb/host/aotg_plat_data.h
@@ -0,0 +1,22 @@
+
+#ifndef __AOTG_PLAT_DATA_H__
+#define __AOTG_PLAT_DATA_H__
+
+struct aotg_plat_data {
+	void __iomem *usbecs;
+	void __iomem *usbpll;
+	u32 usbpll_bits;
+	void __iomem *devrst;
+	u32 devrst_bits;
+	int no_hs;
+};
+
+int aotg0_device_init(int power_only);
+void aotg0_device_exit(int power_only);
+
+int aotg1_device_init(int power_only);
+void aotg1_device_exit(int power_only);
+extern void aotg_hub_unregister(int dev_id);
+extern int aotg_hub_register(int dev_id);
+
+#endif
diff --git a/drivers/usb/host/aotg_regs.h b/drivers/usb/host/aotg_regs.h
new file mode 100644
index 0000000..a286b9b
--- /dev/null
+++ b/drivers/usb/host/aotg_regs.h
@@ -0,0 +1,1527 @@
+/*
+ * for Actions AOTG 
+ *
+ */
+
+#ifndef  __AOTG_REGS_H__
+#define  __AOTG_REGS_H__
+
+//#include <mach/hardware.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+//#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+#define USBH_BASE0				0xB0600000
+#define USBH_BASE1				0xB0700000
+
+#define AOTG_REGS_SIZE		(64*1024)    //64k
+
+#define	    HCIN0BC             0x00000000
+#define	    HCOUT0BC            0x00000001
+#define     EP0CS           	0x00000002
+
+#define     HCIN1BC         	0x00000008
+#define     HCIN2BC         	0x00000010
+#define     HCIN3BC         	0x00000018
+#define     HCIN4BC         	0x00000020
+#define     HCIN5BC         	0x00000028
+#define     HCIN6BC         	0x00000030
+#define     HCIN7BC         	0x00000038
+#define     HCIN8BC         	0x00000040
+#define     HCIN9BC         	0x00000048
+#define     HCIN10BC            0x00000050
+#define     HCIN11BC            0x00000058
+#define     HCIN12BC            0x00000060
+#define     HCIN13BC            0x00000068
+#define     HCIN14BC            0x00000070
+#define     HCIN15BC            0x00000078
+
+#define     HCIN1BCL            0x00000008
+#define     HCIN2BCL            0x00000010
+#define     HCIN3BCL            0x00000018
+#define     HCIN4BCL            0x00000020
+#define     HCIN5BCL            0x00000028
+#define     HCIN6BCL            0x00000030
+#define     HCIN7BCL            0x00000038
+#define     HCIN8BCL            0x00000040
+#define     HCIN9BCL            0x00000048
+#define     HCIN10BCL           0x00000050
+#define     HCIN11BCL           0x00000058
+#define     HCIN12BCL           0x00000060
+#define     HCIN13BCL           0x00000068
+#define     HCIN14BCL           0x00000070
+#define     HCIN15BCL           0x00000078
+
+#define     HCIN1BCH            0x00000009
+#define     HCIN2BCH            0x00000011
+#define     HCIN3BCH            0x00000019
+#define     HCIN4BCH            0x00000021
+#define     HCIN5BCH            0x00000029
+#define     HCIN6BCH            0x00000031
+#define     HCIN7BCH            0x00000039
+#define     HCIN8BCH            0x00000041
+#define     HCIN9BCH            0x00000049
+#define     HCIN10BCH           0x00000051
+#define     HCIN11BCH           0x00000059
+#define     HCIN12BCH           0x00000061
+#define     HCIN13BCH           0x00000069
+#define     HCIN14BCH           0x00000071
+#define     HCIN15BCH           0x00000079
+
+#define     HCIN1CON            0x0000000A
+#define     HCIN2CON            0x00000012
+#define     HCIN3CON            0x0000001A
+#define     HCIN4CON            0x00000022
+#define     HCIN5CON            0x0000002A
+#define     HCIN6CON            0x00000032
+#define     HCIN7CON            0x0000003A
+#define     HCIN8CON            0x00000042
+#define     HCIN9CON            0x0000004A
+#define     HCIN10CON           0x00000052
+#define     HCIN11CON           0x0000005A
+#define     HCIN12CON           0x00000062
+#define     HCIN13CON           0x0000006A
+#define     HCIN14CON           0x00000072
+#define     HCIN15CON           0x0000007A
+
+#define     HCIN1CS         0x0000000B
+#define     HCIN2CS         0x00000013
+#define     HCIN3CS         0x0000001B
+#define     HCIN4CS         0x00000023
+#define     HCIN5CS         0x0000002B
+#define     HCIN6CS         0x00000033
+#define     HCIN7CS         0x0000003B
+#define     HCIN8CS         0x00000043
+#define     HCIN9CS         0x0000004B
+#define     HCIN10CS            0x00000053
+#define     HCIN11CS            0x0000005B
+#define     HCIN12CS            0x00000063
+#define     HCIN13CS            0x0000006B
+#define     HCIN14CS            0x00000073
+#define     HCIN15CS            0x0000007B
+
+#define     HCOUT1BC            0x0000000C
+#define     HCOUT2BC            0x00000014
+#define     HCOUT3BC            0x0000001C
+#define     HCOUT4BC            0x00000024
+#define     HCOUT5BC            0x0000002C
+#define     HCOUT6BC            0x00000034
+#define     HCOUT7BC            0x0000003C
+#define     HCOUT8BC            0x00000044
+#define     HCOUT9BC            0x0000004C
+#define     HCOUT10BC           0x00000054
+#define     HCOUT11BC           0x0000005C
+#define     HCOUT12BC           0x00000064
+#define     HCOUT13BC           0x0000006C
+#define     HCOUT14BC           0x00000074
+#define     HCOUT15BC           0x0000007C
+
+#define     HCOUT1BCL           0x0000000C
+#define     HCOUT2BCL           0x00000014
+#define     HCOUT3BCL           0x0000001C
+#define     HCOUT4BCL           0x00000024
+#define     HCOUT5BCL           0x0000002C
+#define     HCOUT6BCL           0x00000034
+#define     HCOUT7BCL           0x0000003C
+#define     HCOUT8BCL           0x00000044
+#define     HCOUT9BCL           0x0000004C
+#define     HCOUT10BCL          0x00000054
+#define     HCOUT11BCL          0x0000005C
+#define     HCOUT12BCL          0x00000064
+#define     HCOUT13BCL          0x0000006C
+#define     HCOUT14BCL          0x00000074
+#define     HCOUT15BCL          0x0000007C
+
+#define     HCOUT1BCH           0x0000000D
+#define     HCOUT2BCH           0x00000015
+#define     HCOUT3BCH           0x0000001D
+#define     HCOUT4BCH           0x00000025
+#define     HCOUT5BCH           0x0000002D
+#define     HCOUT6BCH           0x00000035
+#define     HCOUT7BCH           0x0000003D
+#define     HCOUT8BCH           0x00000045
+#define     HCOUT9BCH           0x0000004D
+#define     HCOUT10BCH          0x00000055
+#define     HCOUT11BCH          0x0000005D
+#define     HCOUT12BCH          0x00000065
+#define     HCOUT13BCH          0x0000006D
+#define     HCOUT14BCH          0x00000075
+#define     HCOUT15BCH          0x0000007D
+
+#define     HCOUT1CON           0x0000000E
+#define     HCOUT2CON           0x00000016
+#define     HCOUT3CON           0x0000001E
+#define     HCOUT4CON           0x00000026
+#define     HCOUT5CON           0x0000002E
+#define     HCOUT6CON           0x00000036
+#define     HCOUT7CON           0x0000003E
+#define     HCOUT8CON           0x00000046
+#define     HCOUT9CON           0x0000004E
+#define     HCOUT10CON          0x00000056
+#define     HCOUT11CON          0x0000005E
+#define     HCOUT12CON          0x00000066
+#define     HCOUT13CON          0x0000006E
+#define     HCOUT14CON          0x00000076
+#define     HCOUT15CON          0x0000007E
+
+#define     HCOUT1CS            0x0000000F
+#define     HCOUT2CS            0x00000017
+#define     HCOUT3CS            0x0000001F
+#define     HCOUT4CS            0x00000027
+#define     HCOUT5CS            0x0000002F
+#define     HCOUT6CS            0x00000037
+#define     HCOUT7CS            0x0000003F
+#define     HCOUT8CS            0x00000047
+#define     HCOUT9CS            0x0000004F
+#define     HCOUT10CS           0x00000057
+#define     HCOUT11CS           0x0000005F
+#define     HCOUT12CS           0x00000067
+#define     HCOUT13CS           0x0000006F
+#define     HCOUT14CS           0x00000077
+#define     HCOUT15CS           0x0000007F
+
+#define     HCEP0CTRL           0x000000C0
+#define     HCOUT1CTRL          0x000000C4
+#define     HCOUT2CTRL          0x000000C8
+#define     HCOUT3CTRL          0x000000CC
+#define     HCOUT4CTRL          0x000000D0
+#define     HCOUT5CTRL          0x000000D4
+#define     HCOUT6CTRL          0x000000D8
+#define     HCOUT7CTRL          0x000000DC
+#define     HCOUT8CTRL          0x000000E0
+#define     HCOUT9CTRL          0x000000E4
+#define     HCOUT10CTRL         0x000000E8
+#define     HCOUT11CTRL         0x000000EC
+#define     HCOUT12CTRL         0x000000F0
+#define     HCOUT13CTRL         0x000000F4
+#define     HCOUT14CTRL         0x000000F8
+#define     HCOUT15CTRL         0x000000FC
+
+#define     HCOUT0ERR           0x000000C1
+#define     HCOUT1ERR           0x000000C5
+#define     HCOUT2ERR           0x000000C9
+#define     HCOUT3ERR           0x000000CD
+#define     HCOUT4ERR           0x000000D1
+#define     HCOUT5ERR           0x000000D5
+#define     HCOUT6ERR           0x000000D9
+#define     HCOUT7ERR           0x000000DD
+#define     HCOUT8ERR           0x000000E1
+#define     HCOUT9ERR           0x000000E5
+#define     HCOUT10ERR          0x000000E9
+#define     HCOUT11ERR          0x000000ED
+#define     HCOUT12ERR          0x000000F1
+#define     HCOUT13ERR          0x000000F5
+#define     HCOUT14ERR          0x000000F9
+#define     HCOUT15ERR          0x000000FD
+
+#define     HCIN1CTRL           0x000000C6
+#define     HCIN2CTRL           0x000000CA
+#define     HCIN3CTRL           0x000000CE
+#define     HCIN4CTRL           0x000000D2
+#define     HCIN5CTRL           0x000000D6
+#define     HCIN6CTRL           0x000000DA
+#define     HCIN7CTRL           0x000000DE
+#define     HCIN8CTRL           0x000000E2
+#define     HCIN9CTRL           0x000000E6
+#define     HCIN10CTRL          0x000000EA
+#define     HCIN11CTRL          0x000000EE
+#define     HCIN12CTRL          0x000000F2
+#define     HCIN13CTRL          0x000000F6
+#define     HCIN14CTRL          0x000000FA
+#define     HCIN15CTRL          0x000000FE
+
+#define     HCIN0ERR            0x000000C3
+#define     HCIN1ERR            0x000000C7
+#define     HCIN2ERR            0x000000CB
+#define     HCIN3ERR            0x000000CF
+#define     HCIN4ERR            0x000000D3
+#define     HCIN5ERR            0x000000D7
+#define     HCIN6ERR            0x000000DB
+#define     HCIN7ERR            0x000000DF
+#define     HCIN8ERR            0x000000E3
+#define     HCIN9ERR            0x000000E7
+#define     HCIN10ERR           0x000000EB
+#define     HCIN11ERR           0x000000EF
+#define     HCIN12ERR           0x000000F3
+#define     HCIN13ERR           0x000000F7
+#define     HCIN14ERR           0x000000FB
+#define     HCIN15ERR           0x000000FF
+
+#define     EP0INDATA_W0            0x00000100
+#define     EP0INDATA_W1            0x00000104
+#define     EP0INDATA_W2            0x00000108
+#define     EP0INDATA_W3            0x0000010C
+#define     EP0INDATA_W4            0x00000110
+#define     EP0INDATA_W5            0x00000114
+#define     EP0INDATA_W6            0x00000118
+#define     EP0INDATA_W7            0x0000011C
+#define     EP0INDATA_W8            0x00000120
+#define     EP0INDATA_W9            0x00000124
+#define     EP0INDATA_W10           0x00000128
+#define     EP0INDATA_W11           0x0000012C
+#define     EP0INDATA_W12           0x00000130
+#define     EP0INDATA_W13           0x00000134
+#define     EP0INDATA_W14           0x00000138
+#define     EP0INDATA_W15           0x0000013C
+#define     EP0OUTDATA_W0           0x00000140
+#define     EP0OUTDATA_W1           0x00000144
+#define     EP0OUTDATA_W2           0x00000148
+#define     EP0OUTDATA_W3           0x0000014C
+#define     EP0OUTDATA_W4           0x00000150
+#define     EP0OUTDATA_W5           0x00000154
+#define     EP0OUTDATA_W6           0x00000158
+#define     EP0OUTDATA_W7           0x0000015C
+#define     EP0OUTDATA_W8           0x00000160
+#define     EP0OUTDATA_W9           0x00000164
+#define     EP0OUTDATA_W10          0x00000168
+#define     EP0OUTDATA_W11          0x0000016C
+#define     EP0OUTDATA_W12          0x00000170
+#define     EP0OUTDATA_W13          0x00000174
+#define     EP0OUTDATA_W14          0x00000178
+#define     EP0OUTDATA_W15          0x0000017C
+#define     SETUPDATA_W0            0x00000180
+#define     SETUPDATA_W1            0x00000184
+
+
+#if 0
+/////////////////////////////////////////////////////
+/*******  for device.  *****************************/
+/////////////////////////////////////////////////////
+#define OUT0BC                  0x00000000
+#define IN0BC                   0x00000001
+
+#define OUT1BCL                 0x00000008
+#define OUT1BCH                 0x00000009
+#define OUT1CON                 0x0000000A
+#define OUT1CS                  0x0000000B
+#define IN1BCL                  0x0000000C
+#define IN1BCH                  0x0000000D
+#define IN1CON                  0x0000000E
+#define IN1CS                   0x0000000F
+#define OUT2BCL                 0x00000010
+#define OUT2BCH                 0x00000011
+#define OUT2CON                 0x00000012
+#define OUT2CS                  0x00000013
+#define IN2BCL                  0x00000014
+#define IN2BCH                  0x00000015
+#define IN2CON                  0x00000016
+#define IN2CS                   0x00000017
+#define OUT3BCL                 0x00000018
+#define OUT3BCH                 0x00000019
+#define OUT3CON                 0x0000001A
+#define OUT3CS                  0x0000001B
+#define IN3BCL                  0x0000001C
+#define IN3BCH                  0x0000001D
+#define IN3CON                  0x0000001E
+#define IN3CS                   0x0000001F
+#define OUT4BCL                 0x00000020
+#define OUT4BCH                 0x00000021
+#define OUT4CON                 0x00000022
+#define OUT4CS                  0x00000023
+#define IN4BCL                  0x00000024
+#define IN4BCH                  0x00000025
+#define IN4CON                  0x00000026
+#define IN4CS                   0x00000027
+#define OUT5BCL                 0x00000028
+#define OUT5BCH                 0x00000029
+#define OUT5CON                 0x0000002A
+#define OUT5CS                  0x0000002B
+#define IN5BCL                  0x0000002C
+#define IN5BCH                  0x0000002D
+#define IN5CON                  0x0000002E
+#define IN5CS                   0x0000002F
+
+//#define FIFO1DATA               0x00000084
+//#define FIFO2DATA               0x00000088
+//#define FIFO3DATA               0x0000008C
+//#define FIFO4DATA               0x00000090
+//#define FIFO5DATA               0x00000094
+//#define EP0INDAT                0x00000100
+//#define HCEP0OUTDAT             0x00000100
+#endif
+
+
+#if 0
+/***************  for 0-7 ep to 0-15 ep. *****************/
+//#define IN07IRQ                 0x00000188
+//#define HCOUT07IRQ              0x00000188
+//#define OUT07IRQ                0x0000018A
+//#define HCIN07IRQ               0x0000018A
+//#define USBIRQ                  0x0000018C
+//#define OUT07PNGIRQ             0x0000018E
+//#define INTXKIRQ                0x00000190
+//#define OUTXTOKIRQ              0x00000190
+//#define OUT07EMPTIRQ            0x00000191
+//#define HCIN07EMPTIRQ           0x00000191
+//#define IN07IEN                 0x00000194
+//#define HCOUT07IEN              0x00000194
+//#define OUT07IEN                0x00000196
+//#define HCIN07IEN               0x00000196
+//#define USBIEN                  0x00000198
+//#define OUT07PNGIEN             0x0000019A
+//#define INTXKIEN                0x0000019C
+//#define OUTXTOKIEN              0x0000019D
+#endif
+
+#define     HCOUTxIRQ0          0x00000188
+#define     HCOUTxIRQ1          0x00000189
+#define     HCINxIRQ0           0x0000018A
+#define     HCINxIRQ1           0x0000018B
+#define     USBIRQ              0x0000018C
+#define     HCINxPNGIRQ0            0x0000018E
+#define     HCINxPNGIRQ1            0x0000018F
+#define     HCOUTxTOKIRQ0           0x00000190
+#define     HCOUTxTOKIRQ1           0x00000191
+#define     HCINxTOKIRQ0            0x00000192
+#define     HCINxTOKIRQ1            0x00000193
+#define     HCOUTxIEN0          0x00000194
+#define     HCOUTxIEN1          0x00000195
+#define     HCINxIEN0           0x00000196
+#define     HCINxIEN1           0x00000197
+#define     USBIEN              0x00000198
+#define     HCINxPNGIEN0            0x0000019A
+#define     HCINxPNGIEN1            0x0000019B
+#define     HCOUTxTOKIEN0           0x0000019C
+#define     HCOUTxTOKIEN1           0x0000019D
+#define     HCINxTOKIEN0            0x0000019E
+#define     HCINxTOKIEN1            0x0000019F
+
+#define IVECT                   0x000001A0
+#define ENDPRST                 0x000001A2
+//#define HCENDPRST               0x000001A2
+#define USBCS                   0x000001A3
+#define FRMNRL                  0x000001A4
+#define     FRMNRH              0x000001A5
+//#define FRMNFH                  0x000001A5
+#define FNADDR                  0x000001A6
+#define CLKGATE                 0x000001A7
+//#define FIFOCTRL                0x000001A8
+#define HCTRAINTERVAL		0x000001A8
+#define HCPORTCTRL              0x000001AB
+#define HCFRMNRL                0x000001AC
+#define HCFRMNRH                0x000001AD
+#define HCFRMREMAINL            0x000001AE
+#define HCFRMREMAINH            0x000001AF
+
+#if 0
+/************** ep0-7 to ep0-15 ******************/
+//#define HCIN07ERRIRQ            0x000001B4
+//#define HCOUT07ERRIRQ           0x000001B6
+//#define HCIN07ERRIEN            0x000001B8
+//#define HCOUT07ERRIEN           0x000001BA
+#endif
+#define     HCINxERRIRQ0            0x000001B4
+#define     HCINxERRIRQ1            0x000001B5
+#define     HCOUTxERRIRQ0           0x000001B6
+#define     HCOUTxERRIRQ1           0x000001B7
+#define     HCINxERRIEN0            0x000001B8
+#define     HCINxERRIEN1            0x000001B9
+#define     HCOUTxERRIEN0           0x000001BA
+#define     HCOUTxERRIEN1           0x000001BB
+
+#define OTGIRQ                  0x000001BC
+#define OTGSTATE                0x000001BD
+#define OTGCTRL                 0x000001BE
+#define OTGSTATUS               0x000001BF
+#define OTGIEN                  0x000001C0
+#define TAAIDLBDIS              0x000001C1
+#define TAWAITBCON              0x000001C2
+#define TBVBUSPLS               0x000001C3
+//#define TBVBUSDISCHPLS          0x000001C7
+#define     TBVBUSDISPLS            0x000001C7
+
+#define     HCIN0MAXPCK         0x000001E0
+#define     HCIN1MAXPCK         0x000001E2
+#define     HCIN2MAXPCK         0x000001E4
+#define     HCIN3MAXPCK         0x000001E6
+#define     HCIN4MAXPCK         0x000001E8
+#define     HCIN5MAXPCK         0x000001EA
+#define     HCIN6MAXPCK         0x000001EC
+#define     HCIN7MAXPCK         0x000001EE
+#define     HCIN8MAXPCK         0x000001F0
+#define     HCIN9MAXPCK         0x000001F2
+#define     HCIN10MAXPCK            0x000001F4
+#define     HCIN11MAXPCK            0x000001F6
+#define     HCIN12MAXPCK            0x000001F8
+#define     HCIN13MAXPCK            0x000001FA
+#define     HCIN14MAXPCK            0x000001FC
+#define     HCIN15MAXPCK            0x000001FE
+#define     HCIN1MAXPCKL            0x000001E2
+#define     HCIN2MAXPCKL            0x000001E4
+#define     HCIN3MAXPCKL            0x000001E6
+#define     HCIN4MAXPCKL            0x000001E8
+#define     HCIN5MAXPCKL            0x000001EA
+#define     HCIN6MAXPCKL            0x000001EC
+#define     HCIN7MAXPCKL            0x000001EE
+#define     HCIN8MAXPCKL            0x000001F0
+#define     HCIN9MAXPCKL            0x000001F2
+#define     HCIN10MAXPCKL           0x000001F4
+#define     HCIN11MAXPCKL           0x000001F6
+#define     HCIN12MAXPCKL           0x000001F8
+#define     HCIN13MAXPCKL           0x000001FA
+#define     HCIN14MAXPCKL           0x000001FC
+#define     HCIN15MAXPCKL           0x000001FE
+#define     HCIN1MAXPCKH            0x000001E3
+#define     HCIN2MAXPCKH            0x000001E5
+#define     HCIN3MAXPCKH            0x000001E7
+#define     HCIN4MAXPCKH            0x000001E9
+#define     HCIN5MAXPCKH            0x000001EB
+#define     HCIN6MAXPCKH            0x000001ED
+#define     HCIN7MAXPCKH            0x000001EF
+#define     HCIN8MAXPCKH            0x000001F1
+#define     HCIN9MAXPCKH            0x000001F3
+#define     HCIN10MAXPCKH           0x000001F5
+#define     HCIN11MAXPCKH           0x000001F7
+#define     HCIN12MAXPCKH           0x000001F9
+#define     HCIN13MAXPCKH           0x000001FB
+#define     HCIN14MAXPCKH           0x000001FD
+#define     HCIN15MAXPCKH           0x000001FF
+
+#define     HCEP0BINTERVAL          0x00000200
+#define     HCIN1BINTERVAL          0x00000208
+#define     HCIN2BINTERVAL          0x00000210
+#define     HCIN3BINTERVAL          0x00000218
+#define     HCIN4BINTERVAL          0x00000220
+#define     HCIN5BINTERVAL          0x00000228
+#define     HCIN6BINTERVAL          0x00000230
+#define     HCIN7BINTERVAL          0x00000238
+#define     HCIN8BINTERVAL          0x00000240
+#define     HCIN9BINTERVAL          0x00000248
+#define     HCIN10BINTERVAL     0x00000250
+#define     HCIN11BINTERVAL     0x00000258
+#define     HCIN12BINTERVAL     0x00000260
+#define     HCIN13BINTERVAL     0x00000268
+#define     HCIN14BINTERVAL     0x00000270
+#define     HCIN15BINTERVAL     0x00000278
+#define     HCEP0ADDR           0x201
+#define     HCIN1ADDR           0x00000209
+#define     HCIN2ADDR           0x00000211
+#define     HCIN3ADDR           0x00000219
+#define     HCIN4ADDR           0x00000221
+#define     HCIN5ADDR           0x00000229
+#define     HCIN6ADDR           0x00000231
+#define     HCIN7ADDR           0x00000239
+#define     HCIN8ADDR           0x00000241
+#define     HCIN9ADDR           0x00000249
+#define     HCIN10ADDR          0x00000251
+#define     HCIN11ADDR          0x00000259
+#define     HCIN12ADDR          0x00000261
+#define     HCIN13ADDR          0x00000269
+#define     HCIN14ADDR          0x00000271
+#define     HCIN15ADDR          0x00000279
+#define     HCEP0PORT           0x00000202
+#define     HCIN1PORT           0x0000020A
+#define     HCIN2PORT           0x00000212
+#define     HCIN3PORT           0x0000021A
+#define     HCIN4PORT           0x00000222
+#define     HCIN5PORT           0x0000022A
+#define     HCIN6PORT           0x00000232
+#define     HCIN7PORT           0x0000023A
+#define     HCIN8PORT           0x00000242
+#define     HCIN9PORT           0x0000024A
+#define     HCIN10PORT          0x00000252
+#define     HCIN11PORT          0x0000025A
+#define     HCIN12PORT          0x00000262
+#define     HCIN13PORT          0x0000026A
+#define     HCIN14PORT          0x00000272
+#define     HCIN15PORT          0x0000027A
+#define     HCEP0SPILITCS           0x00000203
+#define     HCIN1SPILITCS           0x0000020B
+#define     HCIN2SPILITCS           0x00000213
+#define     HCIN3SPILITCS           0x0000021B
+#define     HCIN4SPILITCS           0x00000223
+#define     HCIN5SPILITCS           0x0000022B
+#define     HCIN6SPILITCS           0x00000233
+#define     HCIN7SPILITCS           0x0000023B
+#define     HCIN8SPILITCS           0x00000243
+#define     HCIN9SPILITCS           0x0000024B
+#define     HCIN10SPILITCS          0x00000253
+#define     HCIN11SPILITCS          0x0000025B
+#define     HCIN12SPILITCS          0x00000263
+#define     HCIN13SPILITCS          0x0000026B
+#define     HCIN14SPILITCS          0x00000273
+#define     HCIN15SPILITCS          0x0000027B
+#define     HCOUT1BINTERVAL     0x00000288
+#define     HCOUT2BINTERVAL     0x00000290
+#define     HCOUT3BINTERVAL     0x00000298
+#define     HCOUT4BINTERVAL     0x000002A0
+#define     HCOUT5BINTERVAL     0x000002A8
+#define     HCOUT6BINTERVAL     0x000002B0
+#define     HCOUT7BINTERVAL     0x000002B8
+#define     HCOUT8BINTERVAL     0x000002C0
+#define     HCOUT9BINTERVAL     0x000002C8
+#define     HCOUT10BINTERVAL        0x000002D0
+#define     HCOUT11BINTERVAL        0x000002D8
+#define     HCOUT12BINTERVAL        0x000002E0
+#define     HCOUT13BINTERVAL        0x000002E8
+#define     HCOUT14BINTERVAL        0x000002F0
+#define     HCOUT15BINTERVAL        0x000002F8
+#define     HCOUT1ADDR          0x00000289
+#define     HCOUT2ADDR          0x00000291
+#define     HCOUT3ADDR          0x00000299
+#define     HCOUT4ADDR          0x000002A1
+#define     HCOUT5ADDR          0x000002A9
+#define     HCOUT6ADDR          0x000002B1
+#define     HCOUT7ADDR          0x000002B9
+#define     HCOUT8ADDR          0x000002C1
+#define     HCOUT9ADDR          0x000002C9
+#define     HCOUT10ADDR         0x000002D1
+#define     HCOUT11ADDR         0x000002D9
+#define     HCOUT12ADDR         0x000002E1
+#define     HCOUT13ADDR         0x000002E9
+#define     HCOUT14ADDR         0x000002F1
+#define     HCOUT15ADDR         0x000002F9
+#define     HCOUT1PORT          0x0000028A
+#define     HCOUT2PORT          0x00000292
+#define     HCOUT3PORT          0x0000029A
+#define     HCOUT4PORT          0x000002A2
+#define     HCOUT5PORT          0x000002AA
+#define     HCOUT6PORT          0x000002B2
+#define     HCOUT7PORT          0x000002BA
+#define     HCOUT8PORT          0x000002C2
+#define     HCOUT9PORT          0x000002CA
+#define     HCOUT10PORT         0x000002D2
+#define     HCOUT11PORT         0x000002DA
+#define     HCOUT12PORT         0x000002E2
+#define     HCOUT13PORT         0x000002EA
+#define     HCOUT14PORT         0x000002F2
+#define     HCOUT15PORT         0x000002FA
+#define     HCOUT1SPILITCS          0x0000028B
+#define     HCOUT2SPILITCS          0x00000293
+#define     HCOUT3SPILITCS          0x0000029B
+#define     HCOUT4SPILITCS          0x000002A3
+#define     HCOUT5SPILITCS          0x000002AB
+#define     HCOUT6SPILITCS          0x000002B3
+#define     HCOUT7SPILITCS          0x000002BB
+#define     HCOUT8SPILITCS          0x000002C3
+#define     HCOUT9SPILITCS          0x000002CB
+#define     HCOUT10SPILITCS     0x000002D3
+#define     HCOUT11SPILITCS     0x000002DB
+#define     HCOUT12SPILITCS     0x000002E3
+#define     HCOUT13SPILITCS     0x000002EB
+#define     HCOUT14SPILITCS     0x000002F3
+#define     HCOUT15SPILITCS     0x000002FB
+
+#if 0
+/*************  replaced by new register define. ************/
+#define OUT1STARTADDRESS        0x00000304
+#define OUT1STARTADDRESSL       0x00000304
+#define OUT1STARTADDRESSH       0x00000305
+#define OUT2STARTADDRESS        0x00000308
+#define OUT2STARTADDRESSL       0x00000308
+
+#define OUT3STADDR              0x0000030C
+#define OUT4STADDR              0x00000310
+#define OUT5STADDR              0x00000314
+
+#define OUT2STARTADDRESSH       0x00000309
+#define IN1STARTADDRESS         0x00000344
+#define IN1STARTADDRESSL        0x00000344
+#define IN1STARTADDRESSH        0x00000345
+#define IN2STARTADDRESS         0x00000348
+#define IN2STARTADDRESSL        0x00000348
+#define IN2STARTADDRESSH        0x00000349
+
+#define IN3STADDR               0x0000034C
+#define IN4STADDR               0x00000350
+#define IN5STADDR               0x00000354
+
+#define HCOUT0MAXPCK            0x000003E0
+#define HCOUT1MAXPCKL           0x000003E2
+#define HCOUT1MAXPCKH           0x000003E3
+#define HCOUT2MAXPCKL           0x000003E4
+#define HCOUT2MAXPCKH           0x000003E5
+#define HCOUT3MAXPCKL           0x000003E6
+#define HCOUT3MAXPCKH           0x000003E7
+#define HCOUT4MAXPCKL           0x000003E8
+#define HCOUT4MAXPCKH           0x000003E9
+#define HCOUT5MAXPCKL           0x000003EA
+#define HCOUT5MAXPCKH           0x000003EB
+
+//#define USBERESET               0x00000400
+#define TA_BCON_COUNT           0x00000401
+#define VBUSDBCTIMERL           0x00000402
+#define VBUSDBCTIMERH           0x00000403
+#define VDCTRL                  0x00000404
+#define VDSTATE                 0x00000405
+#define BKDOOR                  0x00000406
+#define DBGMODE                 0x00000407
+#define SRPCTRL                 0x00000408
+//#define USBEIRQ                 0x0000040A
+#define USBEIEN                 0x0000040C
+#define UDMAIRQ                 0x0000040E
+#define UDMAIEN                 0x0000040F
+#define OUTXSHORTPCKIRQ         0x00000410
+#define OUTXSHORTPCKIEN         0x00000412
+#define OUTXNAKCTRL             0x00000414
+#define HCINXSTART              0x00000416
+#define HCINXENDIRQ             0x00000418
+#define HCINXENDIEN             0x0000041A
+
+/* HCINxCounter\BCĴ\E6\C6\F7\B5\C4д\C8\EB\B5\D8ַΪ0x420,0x424,0x428,0x42c,0x430,\B6\C1ȡ\B5\D8ַΪ0x420\A3\AC0x422,0x424,0x426,0x428\A1\A3*/
+//#define HCIN1_COUNTL            0x00000420
+//#define HCIN1_COUNTH            0x00000421
+//#define HCIN2_COUNTL            0x00000422
+//#define HCIN2_COUNTH            0x00000423
+//#define HCIN3_COUNTL            0x00000424
+//#define HCIN3_COUNTH            0x00000425
+//#define HCIN4_COUNTL            0x00000426
+//#define HCIN4_COUNTH            0x00000427
+//#define HCIN5_COUNTL            0x00000428
+//#define HCIN5_COUNTH            0x00000429
+#define HCIN1_COUNTL            0x00000420
+#define HCIN1_COUNTH            0x00000421
+#define HCIN2_COUNTL            0x00000424
+#define HCIN2_COUNTH            0x00000425
+#define HCIN3_COUNTL            0x00000428
+#define HCIN3_COUNTH            0x00000429
+#define HCIN4_COUNTL            0x0000042c
+#define HCIN4_COUNTH            0x0000042d
+#define HCIN5_COUNTL            0x00000430
+#define HCIN5_COUNTH            0x00000431
+
+#define INXBUFEMPTYIRQ          0x00000440
+#define INXBUFEMPTYIEN          0x00000442
+#define INXBUFEMPTYCTRL         0x00000444
+#define UDMA1MEMADDR            0x00000450
+#define UDMA1EPSEL              0x00000454
+#define UDMA1COM                0x00000455
+#define UDMA1CNTL               0x00000458
+#define UDMA1CNTM               0x00000459
+#define UDMA1CNTH               0x0000045A
+#define UDMA1REML               0x0000045C
+#define UDMA1REMM               0x0000045D
+#define UDMA1REMH               0x0000045E
+#define UDMA2MEMADDR            0x00000460
+#define UDMA2EPSEL              0x00000464
+#define UDMA2COM                0x00000465
+#define UDMA2CNTL               0x00000468
+#define UDMA2CNTM               0x00000469
+#define UDMA2CNTH               0x0000046A
+#define UDMA2REML               0x0000046C
+#define UDMA2REMM               0x0000046D
+#define UDMA2REMH               0x0000046E
+#endif
+
+#define     HCIN1STADDR         0x00000304
+#define     HCIN2STADDR         0x00000308
+#define     HCIN3STADDR         0x0000030C
+#define     HCIN4STADDR         0x00000310
+#define     HCIN5STADDR         0x00000314
+#define     HCIN6STADDR         0x00000318
+#define     HCIN7STADDR         0x0000031C
+#define     HCIN8STADDR         0x00000320
+#define     HCIN9STADDR         0x00000324
+#define     HCIN10STADDR            0x00000328
+#define     HCIN11STADDR            0x0000032C
+#define     HCIN12STADDR            0x00000330
+#define     HCIN13STADDR            0x00000334
+#define     HCIN14STADDR            0x00000338
+#define     HCIN15STADDR            0x0000033C
+#define     HCOUT1STADDR            0x00000344
+#define     HCOUT2STADDR            0x00000348
+#define     HCOUT3STADDR            0x0000034C
+#define     HCOUT4STADDR            0x00000350
+#define     HCOUT5STADDR            0x00000354
+#define     HCOUT6STADDR            0x00000358
+#define     HCOUT7STADDR            0x0000035C
+#define     HCOUT8STADDR            0x00000360
+#define     HCOUT9STADDR            0x00000364
+#define     HCOUT10STADDR           0x00000368
+#define     HCOUT11STADDR           0x0000036C
+#define     HCOUT12STADDR           0x00000370
+#define     HCOUT13STADDR           0x00000374
+#define     HCOUT14STADDR           0x00000378
+#define     HCOUT15STADDR           0x0000037C
+#define     HCOUT1MAXPCK            0x000003E2
+#define     HCOUT2MAXPCK            0x000003E4
+#define     HCOUT3MAXPCK            0x000003E6
+#define     HCOUT4MAXPCK            0x000003E8
+#define     HCOUT5MAXPCK            0x000003EA
+#define     HCOUT6MAXPCK            0x000003EC
+#define     HCOUT7MAXPCK            0x000003EE
+#define     HCOUT8MAXPCK            0x3F0
+#define     HCOUT9MAXPCK            0x000003F2
+#define     HCOUT10MAXPCK           0x000003F4
+#define     HCOUT11MAXPCK           0x000003F6
+#define     HCOUT12MAXPCK           0x000003F8
+#define     HCOUT13MAXPCK           0x000003FA
+#define     HCOUT14MAXPCK           0x000003FC
+#define     HCOUT15MAXPCK           0x000003FE
+#define     HCOUT1MAXPCKL           0x000003E2
+#define     HCOUT2MAXPCKL           0x000003E4
+#define     HCOUT3MAXPCKL           0x000003E6
+#define     HCOUT4MAXPCKL           0x000003E8
+#define     HCOUT5MAXPCKL           0x000003EA
+#define     HCOUT6MAXPCKL           0x000003EC
+#define     HCOUT7MAXPCKL           0x000003EE
+#define     HCOUT8MAXPCKL           0x3F0
+#define     HCOUT9MAXPCKL           0x000003F2
+#define     HCOUT10MAXPCKL          0x000003F4
+#define     HCOUT11MAXPCKL          0x000003F6
+#define     HCOUT12MAXPCKL          0x000003F8
+#define     HCOUT13MAXPCKL          0x000003FA
+#define     HCOUT14MAXPCKL          0x000003FC
+#define     HCOUT15MAXPCKL          0x000003FE
+#define     HCOUT1MAXPCKH           0x000003E3
+#define     HCOUT2MAXPCKH           0x000003E5
+#define     HCOUT3MAXPCKH           0x000003E7
+#define     HCOUT4MAXPCKH           0x000003E9
+#define     HCOUT5MAXPCKH           0x000003EB
+#define     HCOUT6MAXPCKH           0x000003ED
+#define     HCOUT7MAXPCKH           0x000003EF
+#define     HCOUT8MAXPCKH           0x3F1
+#define     HCOUT9MAXPCKH           0x000003F3
+#define     HCOUT10MAXPCKH          0x000003F5
+#define     HCOUT11MAXPCKH          0x000003F7
+#define     HCOUT12MAXPCKH          0x000003F9
+#define     HCOUT13MAXPCKH          0x000003FB
+#define     HCOUT14MAXPCKH          0x000003FD
+#define     HCOUT15MAXPCKH          0x000003FF
+#define     HCINxDMASTART0          0x00000400
+#define     HCINxDMASTART1          0x00000401
+#define     HCINDMAERROR            0x00000402
+#define     HCINxDMAIRQ0            0x00000404
+#define     HCINxDMAIRQ1            0x00000405
+#define     HCINxDMAIEN0            0x00000406
+#define     HCINxDMAIEN1            0x00000407
+#define     HCIN1DMASTADDR          0x00000408
+#define     HCIN2DMASTADDR          0x00000410
+#define     HCIN3DMASTADDR          0x00000418
+#define     HCIN4DMASTADDR          0x00000420
+#define     HCIN5DMASTADDR          0x00000428
+#define     HCIN6DMASTADDR          0x00000430
+#define     HCIN7DMASTADDR          0x00000438
+#define     HCIN8DMASTADDR          0x00000440
+#define     HCIN9DMASTADDR          0x00000448
+#define     HCIN10DMASTADDR     0x00000450
+#define     HCIN11DMASTADDR     0x00000458
+#define     HCIN12DMASTADDR     0x00000460
+#define     HCIN13DMASTADDR     0x00000468
+#define     HCIN14DMASTADDR     0x00000470
+#define     HCIN15DMASTADDR     0x00000478
+#define     HCIN1DMACOUNTER     0x0000040C
+#define     HCIN2DMACOUNTER     0x00000414
+#define     HCIN3DMACOUNTER     0x0000041C
+#define     HCIN4DMACOUNTER     0x00000424
+#define     HCIN5DMACOUNTER     0x0000042C
+#define     HCIN6DMACOUNTER     0x00000434
+#define     HCIN7DMACOUNTER     0x0000043C
+#define     HCIN8DMACOUNTER     0x00000444
+#define     HCIN9DMACOUNTER     0x0000044C
+#define     HCIN10DMACOUNTER        0x00000454
+#define     HCIN11DMACOUNTER        0x0000045C
+#define     HCIN12DMACOUNTER        0x00000464
+#define     HCIN13DMACOUNTER        0x0000046C
+#define     HCIN14DMACOUNTER        0x00000474
+#define     HCIN15DMACOUNTER        0x0000047C
+#define     HCOUTxDMASTART0     0x00000480
+#define     HCOUTxDMASTART1     0x00000481
+#define     HCOUTxDMAIRQ0           0x00000484
+#define     HCOUTxDMAIRQ1           0x00000485
+#define     HCOUTxDMAIEN0           0x00000486
+#define     HCOUTxDMAIEN1           0x00000487
+#define     HCOUT1DMASTADDR     0x00000488
+#define     HCOUT2DMASTADDR     0x00000490
+#define     HCOUT3DMASTADDR     0x00000498
+#define     HCOUT4DMASTADDR     0x000004A0
+#define     HCOUT5DMASTADDR     0x000004A8
+#define     HCOUT6DMASTADDR     0x000004B0
+#define     HCOUT7DMASTADDR     0x000004B8
+#define     HCOUT8DMASTADDR     0x000004C0
+#define     HCOUT9DMASTADDR     0x000004C8
+#define     HCOUT10DMASTADDR        0x000004D0
+#define     HCOUT11DMASTADDR        0x000004D8
+#define     HCOUT12DMASTADDR        0x000004E0
+#define     HCOUT13DMASTADDR        0x000004E8
+#define     HCOUT14DMASTADDR        0x000004F0
+#define     HCOUT15DMASTADDR        0x000004F8
+#define     HCOUT1DMACOUNTER        0x0000048C
+#define     HCOUT2DMACOUNTER        0x00000494
+#define     HCOUT3DMACOUNTER        0x0000049C
+#define     HCOUT4DMACOUNTER        0x000004A4
+#define     HCOUT5DMACOUNTER        0x000004AC
+#define     HCOUT6DMACOUNTER        0x000004B4
+#define     HCOUT7DMACOUNTER        0x000004BC
+#define     HCOUT8DMACOUNTER        0x000004C4
+#define     HCOUT9DMACOUNTER        0x000004CC
+#define     HCOUT10DMACOUNTER       0x000004D4
+#define     HCOUT11DMACOUNTER       0x000004DC
+#define     HCOUT12DMACOUNTER       0x000004E4
+#define     HCOUT13DMACOUNTER       0x000004EC
+#define     HCOUT14DMACOUNTER       0x000004F4
+#define     HCOUT15DMACOUNTER       0x000004FC
+#define     USBERESET           0x00000500
+#define     TA_BCON_COUNT           0x00000501
+#define     VBUSDBCTIMERL           0x00000502
+#define     VBUSDBCTIMERH           0x00000503
+#define     VDCTRL              0x00000504
+#define     VDSTATUS            0x00000505
+#define     BKDOOR              0x00000506
+#define     DBGMODE         0x00000507
+#define     SRPCTRL         0x00000508
+#define     USBEIRQ         0x0000050A
+#define     USBEIEN         0x0000050B
+#define     HCINxSHORTPCKIRQ0       0x00000510
+#define     HCINxSHORTPCKIRQ1       0x00000511
+#define     HCINxSHORTPCKIEN0       0x00000512
+#define     HCINxSHORTPCKIEN1       0x00000513
+#define     HCINxZEROPCKIRQ0        0x00000514
+#define     HCINxZEROPCKIRQ1        0x00000515
+#define     HCINxZEROPCKIEN0        0x00000516
+#define     HCINxZEROPCKIEN1        0x00000517
+#define     HCOUTxBUFEMPTYIRQ0      0x00000518
+#define     HCOUTxBUFEMPTYIRQ1      0x00000519
+#define     HCOUTxBUFEMPTYIEN0      0x0000051A
+#define     HCOUTxBUFEMPTYIEN1      0x0000051B
+#define     HCOUTxBUFEMPTYCTRL0     0x0000051C
+#define     HCOUTxBUFEMPTYCTRL1     0x0000051D
+
+
+//linklist regs
+#define	HCDMABCKDOOR	0x00000800
+#define	HCDMAxOVERFLOWIRQ	0x00000808
+#define HCDMAxOVERFLOWIEN	0x0000080C
+
+#define	HCOUT1DMALINKADDR	0x00000910
+#define	HCOUT2DMALINKADDR	0x00000920
+#define	HCOUT3DMALINKADDR	0x00000930
+#define	HCOUT4DMALINKADDR	0x00000940
+#define	HCOUT5DMALINKADDR	0x00000950
+#define	HCOUT6DMALINKADDR	0x00000960
+#define	HCOUT7DMALINKADDR	0x00000970
+#define	HCOUT8DMALINKADDR	0x00000980
+#define	HCOUT9DMALINKADDR	0x00000990
+#define	HCOUT10DMALINKADDR	0x000009A0
+#define	HCOUT11DMALINKADDR	0x000009B0
+#define	HCOUT12DMALINKADDR	0x000009C0
+#define	HCOUT13DMALINKADDR	0x000009D0
+#define	HCOUT14DMALINKADDR	0x000009E0
+#define	HCOUT15DMALINKADDR	0x000009F0
+
+#define HCOUT1DMACURADDR	0x00000914
+#define HCOUT2DMACURADDR	0x00000924
+#define HCOUT3DMACURADDR	0x00000934
+#define HCOUT4DMACURADDR	0x00000944
+#define HCOUT5DMACURADDR	0x00000954
+#define HCOUT6DMACURADDR	0x00000964
+#define HCOUT7DMACURADDR	0x00000974
+#define HCOUT8DMACURADDR	0x00000984
+#define HCOUT9DMACURADDR	0x00000994
+#define HCOUT10DMACURADDR	0x000009A4
+#define HCOUT11DMACURADDR	0x000009B4
+#define HCOUT12DMACURADDR	0x000009C4
+#define HCOUT13DMACURADDR	0x000009D4
+#define HCOUT14DMACURADDR	0x000009E4
+#define HCOUT15DMACURADDR	0x000009F4
+
+#define	HCOUT1DMACTRL	0x00000918
+#define	HCOUT2DMACTRL	0x00000928
+#define	HCOUT3DMACTRL	0x00000938
+#define	HCOUT4DMACTRL	0x00000948
+#define	HCOUT5DMACTRL	0x00000958
+#define	HCOUT6DMACTRL	0x00000968
+#define	HCOUT7DMACTRL	0x00000978
+#define	HCOUT8DMACTRL	0x00000988
+#define	HCOUT9DMACTRL	0x00000998
+#define	HCOUT10DMACTRL	0x000009A8
+#define	HCOUT11DMACTRL	0x000009B8
+#define	HCOUT12DMACTRL	0x000009C8
+#define	HCOUT13DMACTRL	0x000009D8
+#define	HCOUT14DMACTRL	0x000009E8
+#define	HCOUT15DMACTRL	0x000009F8
+
+#define	HCOUT1DMACOMPLETECNT	0x0000091C
+#define	HCOUT2DMACOMPLETECNT	0x0000092C
+#define	HCOUT3DMACOMPLETECNT	0x0000093C
+#define	HCOUT4DMACOMPLETECNT	0x0000094C
+#define	HCOUT5DMACOMPLETECNT	0x0000095C
+#define	HCOUT6DMACOMPLETECNT	0x0000096C
+#define	HCOUT7DMACOMPLETECNT	0x0000097C
+#define	HCOUT8DMACOMPLETECNT	0x0000098C
+#define	HCOUT9DMACOMPLETECNT	0x0000099C
+#define	HCOUT10DMACOMPLETECNT	0x000009AC
+#define	HCOUT11DMACOMPLETECNT	0x000009BC
+#define	HCOUT12DMACOMPLETECNT	0x000009CC
+#define	HCOUT13DMACOMPLETECNT	0x000009DC
+#define	HCOUT14DMACOMPLETECNT	0x000009EC
+#define	HCOUT15DMACOMPLETECNT	0x000009FC
+
+#define	HCIN1DMALINKADDR	0x00000810
+#define	HCIN2DMALINKADDR	0x00000820
+#define	HCIN3DMALINKADDR	0x00000830
+#define	HCIN4DMALINKADDR	0x00000840
+#define	HCIN5DMALINKADDR	0x00000850
+#define	HCIN6DMALINKADDR	0x00000860
+#define	HCIN7DMALINKADDR	0x00000870
+#define	HCIN8DMALINKADDR	0x00000880
+#define	HCIN9DMALINKADDR	0x00000890
+#define	HCIN10DMALINKADDR	0x000008A0
+#define	HCIN11DMALINKADDR	0x000008B0
+#define	HCIN12DMALINKADDR	0x000008C0
+#define	HCIN13DMALINKADDR	0x000008D0
+#define	HCIN14DMALINKADDR	0x000008E0
+#define	HCIN15DMALINKADDR	0x000008F0
+
+#define	HCIN1DMACURADDR		0x00000814
+#define	HCIN2DMACURADDR		0x00000824
+#define	HCIN3DMACURADDR		0x00000834
+#define	HCIN4DMACURADDR		0x00000844
+#define	HCIN5DMACURADDR		0x00000854
+#define	HCIN6DMACURADDR		0x00000864
+#define	HCIN7DMACURADDR		0x00000874
+#define	HCIN8DMACURADDR		0x00000884
+#define	HCIN9DMACURADDR		0x00000894
+#define	HCIN10DMACURADDR	0x000008A4
+#define	HCIN11DMACURADDR	0x000008B4
+#define	HCIN12DMACURADDR	0x000008C4
+#define	HCIN13DMACURADDR	0x000008D4
+#define	HCIN14DMACURADDR	0x000008E4
+#define	HCIN15DMACURADDR	0x000008F4
+
+#define	HCIN1DMACTRL		0x00000818
+#define	HCIN2DMACTRL		0x00000828
+#define	HCIN3DMACTRL		0x00000838
+#define	HCIN4DMACTRL		0x00000848
+#define	HCIN5DMACTRL		0x00000858
+#define	HCIN6DMACTRL		0x00000868
+#define	HCIN7DMACTRL		0x00000878
+#define	HCIN8DMACTRL		0x00000888
+#define	HCIN9DMACTRL		0x00000898
+#define	HCIN10DMACTRL		0x000008A8
+#define	HCIN11DMACTRL		0x000008B8
+#define	HCIN12DMACTRL		0x000008C8
+#define	HCIN13DMACTRL		0x000008D8
+#define	HCIN14DMACTRL		0x000008E8
+#define	HCIN15DMACTRL		0x000008F8
+
+#define HCIN1DMACOMPLETECNT		0x0000081C
+#define HCIN2DMACOMPLETECNT		0x0000082C
+#define HCIN3DMACOMPLETECNT		0x0000083C
+#define HCIN4DMACOMPLETECNT		0x0000084C
+#define HCIN5DMACOMPLETECNT		0x0000085C
+#define HCIN6DMACOMPLETECNT		0x0000086C
+#define HCIN7DMACOMPLETECNT		0x0000087C
+#define HCIN8DMACOMPLETECNT		0x0000088C
+#define HCIN9DMACOMPLETECNT		0x0000089C
+#define HCIN10DMACOMPLETECNT	0x000008AC
+#define HCIN11DMACOMPLETECNT	0x000008BC
+#define HCIN12DMACOMPLETECNT	0x000008CC
+#define HCIN13DMACOMPLETECNT	0x000008DC
+#define HCIN14DMACOMPLETECNT	0x000008EC
+#define HCIN15DMACOMPLETECNT	0x000008FC
+
+
+
+/******************************************************************************/
+/* DMA LINK_LIST */
+/******************************************************************************/
+#define DMACTRL_DMACS	(1 << 0)
+#define DMACTRL_DMACC	(1 << 1)
+
+/******************************************************************************/
+/*OTG external Registers USBEIRQ, USBEIEN. */
+/******************************************************************************/
+#define USBEIRQ_USBIRQ          (0x1 << 7)
+#define USBEIRQ_USBIEN          (0x1 << 7)
+
+/* USBERESET USBERES*/
+#define USBERES_USBRESET        (1 << 0)
+
+/*VDCTRL*/
+#define VDCTRL_VLOAD            (1 << 4)
+#define VDCTRL_VCONTROL(x)      ((x) & 0xf)
+
+/******************************************************************************/
+/*OTG SFR Registers*/
+/******************************************************************************/
+/*OTGIRQ*/
+#define	OTGIRQ_PERIPH	            (1<<4)
+#define	OTGIRQ_VBUSEER		    (1<<3)
+#define	OTGIRQ_LOCSOF	            (1<<2)
+#define	OTGIRQ_SRPDET		    (1<<1)
+#define	OTGIRQ_IDLE		    (1<<0)
+
+/*bit 7:5 reserved*/
+/*OTGSTATE*/
+#define	A_IDLE				        (0x00)
+#define	A_WAIT_VRISE		        (0x01)
+#define	A_WAIT_BCON		            (0x02)
+#define	A_HOST				        (0x03)
+#define	A_SUSPEND			        (0x04)
+#define	A_PHERIPHERAL	            (0x05)
+#define	A_VBUS_ERR		            (0x06)
+#define	A_WAIT_VFAL		            (0x07)
+#define B_IDLE				        (0x08)
+#define	B_PHERIPHERAL	            (0x09)
+#define	B_WAIT_ACON		            (0x0a)
+#define	B_HOST				        (0x0b)
+#define	B_SRP_INIT1		            (0x0c)
+#define	B_SRP_INIT2		            (0x0d)
+#define	B_DISCHRG1		            (0x0e)
+#define	B_DISCHRG2		            (0x0f)
+
+/* OTGSTATE value. */
+/* extra dual-role default-b states */
+/* dual-role default-a */
+#define AOTG_STATE_A_IDLE		0
+#define AOTG_STATE_A_WAIT_VRISE		1
+#define AOTG_STATE_A_WAIT_BCON		2
+#define AOTG_STATE_A_HOST		3
+#define AOTG_STATE_A_SUSPEND		4
+#define AOTG_STATE_A_PERIPHERAL		5
+#define AOTG_STATE_A_VBUS_ERR		6
+#define AOTG_STATE_A_WAIT_VFALL		7
+/* single-role peripheral, and dual-role default-b */
+#define AOTG_STATE_B_IDLE		8
+#define AOTG_STATE_B_PERIPHERAL		9
+#define AOTG_STATE_B_WAIT_ACON		10
+#define AOTG_STATE_B_HOST		11
+#define AOTG_STATE_B_SRP_INIT		12
+#define AOTG_STATE_UNDEFINED		17
+
+/*bit 7:4 reserved*/
+/*OTGCTRL*/
+#define	OTGCTRL_FORCEBCONN	        (1 << 7)
+/*bit 6 reserved*/
+#define	OTGCTRL_SRPDATDETEN 		(1 << 5)
+#define	OTGCTRL_SRPVBUSDETEN 		(1 << 4)
+#define	OTGCTRL_BHNPEN				(1 << 3)
+#define	OTGCTRL_ASETBHNPEN			(1 << 2)
+#define	OTGCTRL_ABUSDROP			(1 << 1)
+#define	OTGCTRL_BUSREQ				(1 << 0)
+
+/*OTGSTATUS*/
+/*bit 7 reserved*/
+#define	OTGSTATUS_ID	        	(1 << 6)
+#define	OTGSTATUS_AVBUSSVAL 		(1 << 5)
+#define	OTGSTATUS_BSESSEND			(1 << 4)
+#define	OTGSTATUS_ASESSVAL			(1 << 3)
+#define	OTGSTATUS_BSESSVAL			(1 << 2)
+#define	OTGSTATUS_CONN				(1 << 1)
+#define	OTGSTATUS_BSE0SRP			(1 << 0)
+
+/*OTGIEN*/
+/*bit 7:5 reserved*/
+#define	OTGIEN_PERIPH	            (1 << 4)
+#define	OTGIEN_VBUSEER		        (1 << 3)
+#define	OTGIEN_LOCSOF	            (1 << 2)
+#define	OTGIEN_SRPDET		        (1 << 1)
+#define	OTGIEN_IDLE			        (1 << 0)
+
+/*HCEP0CTRL*/
+#define HCEP0CTRL_ENDPNR(x)         (((x) & 0xf) << 0)
+/*bit 7:4 reserved*/
+
+/* HCINxERR */
+#define	HCINxERR_TYPE_MASK		(0xf << 2)
+/*
+ * 0000 \A8C reserved (no error)
+ * 0001 \A8C CRC error
+ * 0010 \A8C data toggle mismatch
+ * 0011 \A8C endpoint sent STALL handshake
+ * 0100 \A8C no endpoint handshake (timeout)
+ * 0101 \A8C PID error (pid check=error or unknown PID)
+ * 0110 \A8C Data Overrun (too long packet \A8C babble)
+ * 0111 \A8C Data Underrun (packet shorter than MaxPacketSize)
+ * 1xxx \A8C Spilit Transaction Error, reference to HCOUTxSPILITCS register
+*/
+#define	HCINxERR_NO_ERR			(0x0 << 2)
+#define	HCINxERR_CRC_ERR		(0x1 << 2)
+#define	HCINxERR_TOG_ERR		(0x2 << 2)
+#define	HCINxERR_STALL			(0x3 << 2)
+#define	HCINxERR_TIMEOUT		(0x4 << 2)
+#define	HCINxERR_PID_ERR		(0x5 << 2)
+#define	HCINxERR_OVER_RUN		(0x6 << 2)
+#define	HCINxERR_UNDER_RUN		(0x7 << 2)
+#define	HCINxERR_SPLIET			(0x8 << 2)
+#define	HCINxERR_RESEND			(1 << 6)
+
+/*HCOUTXCTRL*/
+//#define HCOUTXCTRL(x)               (((x) & 0xf) << 0)
+/*bit 7:4 reserved*/
+
+
+/******************************************************************************/
+/*Device Mode Special Function Registers*/
+/******************************************************************************/
+/*EP0CS*/
+/*bit 7 reserved*/
+#define EP0CS_HCSETTOOGLE           (1 << 6)
+#define EP0CS_HCCLRTOOGLE           (1 << 5)
+#define EP0CS_HCSET                 (1 << 4)
+#define EP0CS_HCINBSY		        (1 << 3)
+#define	EP0CS_HCOUTBSY	            (1 << 2)
+#define EP0CS_OUTBSY	            (1 << 3)
+#define	EP0CS_INBSY	                (1 << 2)
+#define	EP0CS_HSNAK	                (1 << 1)
+#define	EP0CS_STALL	                (1 << 0)
+
+/*EPXCS host & device*/
+/* HCIN1CS */
+/*bit 7 reserved*/
+//#define	EPCS_AUTO_IN		        (1 << 4)
+//#define	EPCS_AUTO_OUT		        (1 << 4)
+#define EPCS_NPAK                   	(0x3 << 2)
+#define	EPCS_BUSY		       (1 << 1)
+#define	EPCS_ERR		       (1 << 0)
+
+/*EPXCON host & device*/
+#define	EPCON_VAL	                (1 << 7)
+#define	EPCON_STALL	                (1 << 6)
+#define	EPCON_TYPE                  (0x3 << 2)
+#define	EPCON_TYPE_INT		        (0x3 << 2)
+#define	EPCON_TYPE_BULK	            (0x2 << 2)
+#define	EPCON_TYPE_ISO		        (0x1 << 2)
+#define	EPCON_BUF                   (0x03)
+#define	EPCON_BUF_QUAD	            (0x03)
+#define	EPCON_BUF_TRIPLE	        (0x02)
+#define	EPCON_BUF_DOUBLE	        (0x01)
+#define	EPCON_BUF_SINGLE	        (0x00)
+
+/*OUTXIRQ*/
+//#define OUTXIRQ(x)                  (1 << (x))
+/*INXIRQ*/
+//#define INXIRQ(x)                   (1 << (x))
+
+/*USBIRQ*/
+#define	USBIRQ_HS	                (1 << 5)
+#define	USBIRQ_URES	                (1 << 4)
+#define	USBIRQ_SUSP	                (1 << 3)
+#define	USBIRQ_SUTOK	            (1 << 2)
+#define	USBIRQ_SOF	                (1 << 1)
+#define	USBIRQ_SUDAV	            (1 << 0)
+
+/*OUTXIEN*/
+//#define OUTXIEN(x)                  (1 << (x))
+/*INXIEN*/
+//#define INXIEN(x)                   (1 << (x))
+
+/*USBIEN*/
+/*bit 7:6 reserved*/
+#define	USBIEN_HS	                (1 << 5)
+#define	USBIEN_URES               	(1 << 4)
+#define	USBIEN_SUSP             	(1 << 3)
+#define	USBIEN_SUTOK            	(1 << 2)
+#define	USBIEN_SOF	                (1 << 1)
+#define	USBIEN_SUDAV            	(1 << 0)
+
+/* IVECT, USB Interrupt Vector. */
+//#define UIV_OTGIRQ          (0xd8)
+
+#define UIV_SUDAV           0x01
+#define UIV_SOF             0x02
+#define UIV_SUTOK           0x03
+#define UIV_SUSPEND         0x04
+#define UIV_USBRESET        0x05
+#define UIV_HSPEED          0x06
+
+/* otg status. */
+#define UIV_IDLE            0x07
+#define UIV_SRPDET          0x08
+#define UIV_LOCSOF          0x09
+#define UIV_VBUSERR         0x0a
+#define UIV_PERIPH          0x0b
+
+#define UIV_HCOUT0ERR       0x10
+#define UIV_EP0IN           0x20
+#define UIV_HCEP0OUT        0x20
+#define UIV_IN0TOKEN        0x30
+#define UIV_HCIN0ERR        0x40
+#define UIV_EP0OUT          0x50
+#define UIV_HCEP0IN         0x50
+#define UIV_OUT0TOKEN       0x60
+#define UIV_EP0PING         0x70
+
+#define UIV_HCOUT1ERR       0x11
+#define UIV_EP1IN           0x21
+#define UIV_HCEP1OUT        0x21
+#define UIV_IN0T1KEN        0x31
+#define UIV_HCIN1ERR        0x41
+#define UIV_EP1OUT          0x51
+#define UIV_HCEP1IN         0x51
+#define UIV_OUT1TOKEN       0x61
+#define UIV_EP1PING         0x71
+
+#define UIV_HCOUT2ERR       0x12
+#define UIV_EP2IN           0x22
+#define UIV_HCEP2OUT        0x22
+#define UIV_IN2TOKEN        0x32
+#define UIV_HCIN2ERR        0x42
+#define UIV_EP2OUT          0x52
+#define UIV_HCEP2IN         0x52
+#define UIV_OUT2TOKEN       0x62
+#define UIV_EP2PING         0x72
+
+#define UIV_HCOUT3ERR       0x13
+#define UIV_EP3IN           0x23
+#define UIV_HCEP3OUT        0x23
+#define UIV_IN3TOKEN        0x33
+#define UIV_HCIN3ERR        0x43
+#define UIV_EP3OUT          0x53
+#define UIV_HCEP3IN         0x53
+#define UIV_OUT3TOKEN       0x63
+#define UIV_EP3PING         0x73
+
+#define UIV_HCOUT4ERR       0x14
+#define UIV_EP4IN           0x24
+#define UIV_HCEP4OUT        0x24
+#define UIV_IN4TOKEN        0x34
+#define UIV_HCIN4ERR        0x44
+#define UIV_EP4OUT          0x54
+#define UIV_HCEP4IN         0x54
+#define UIV_OUT4TOKEN       0x64
+#define UIV_EP4PING         0x74
+
+#define UIV_HCOUT5ERR       0x15
+#define UIV_EP5IN           0x25
+#define UIV_HCEP5OUT        0x25
+#define UIV_IN5TOKEN        0x35
+#define UIV_HCIN5ERR        0x45
+#define UIV_EP5OUT          0x55
+#define UIV_HCEP5IN         0x55
+#define UIV_OUT5TOKEN       0x65
+#define UIV_EP5PING         0x75
+
+#define UIV_HCOUT6ERR       0x16
+#define UIV_EP6IN           0x26
+#define UIV_HCEP6OUT        0x26
+#define UIV_IN6TOKEN        0x36
+#define UIV_HCIN6ERR        0x46
+#define UIV_EP6OUT          0x56
+#define UIV_HCEP6IN         0x56
+#define UIV_OUT6TOKEN       0x66
+#define UIV_EP6PING         0x76
+
+#define UIV_HCOUT7ERR       0x17
+#define UIV_EP7IN           0x27
+#define UIV_HCEP7OUT        0x27
+#define UIV_IN7TOKEN        0x37
+#define UIV_HCIN7ERR        0x47
+#define UIV_EP7OUT          0x57
+#define UIV_HCEP7IN         0x57
+#define UIV_OUT7TOKEN       0x67
+#define UIV_EP7PING         0x77
+
+#define UIV_HCOUT8ERR       0x18
+#define UIV_EP8IN           0x28
+#define UIV_HCEP8OUT        0x28
+#define UIV_IN8TOKEN        0x38
+#define UIV_HCIN8ERR        0x48
+#define UIV_EP8OUT          0x58
+#define UIV_HCEP8IN         0x58
+#define UIV_OUT8TOKEN       0x68
+#define UIV_EP8PING         0x78
+
+#define UIV_HCOUT9ERR       0x19
+#define UIV_EP9IN           0x29
+#define UIV_HCEP9OUT        0x29
+#define UIV_IN9TOKEN        0x39
+#define UIV_HCIN9ERR        0x49
+#define UIV_EP9OUT          0x59
+#define UIV_HCEP9IN         0x59
+#define UIV_OUT9TOKEN       0x69
+#define UIV_EP9PING         0x79
+
+#define UIV_HCOUT10ERR       0x1a
+#define UIV_EP10IN           0x2a
+#define UIV_HCEP10OUT        0x2a
+#define UIV_IN10TOKEN        0x3a
+#define UIV_HCIN10ERR        0x4a
+#define UIV_EP10OUT          0x5a
+#define UIV_HCEP10IN         0x5a
+#define UIV_OUT10TOKEN       0x6a
+#define UIV_EP10PING         0x7a
+
+#define UIV_HCOUT11ERR       0x1b
+#define UIV_EP11IN           0x2b
+#define UIV_HCEP11OUT        0x2b
+#define UIV_IN11TOKEN        0x3b
+#define UIV_HCIN11ERR        0x4b
+#define UIV_EP11OUT          0x5b
+#define UIV_HCEP11IN         0x5b
+#define UIV_OUT11TOKEN       0x6b
+#define UIV_EP11PING         0x7b
+
+#define UIV_HCOUT12ERR       0x1c
+#define UIV_EP12IN           0x2c
+#define UIV_HCEP12OUT        0x2c
+#define UIV_IN12TOKEN        0x3c
+#define UIV_HCIN12ERR        0x4c
+#define UIV_EP12OUT          0x5c
+#define UIV_HCEP12IN         0x5c
+#define UIV_OUT12TOKEN       0x6c
+#define UIV_EP12PING         0x7c
+
+#define UIV_HCOUT13ERR       0x1d
+#define UIV_EP13IN           0x2d
+#define UIV_HCEP13OUT        0x2d
+#define UIV_IN13TOKEN        0x3d
+#define UIV_HCIN13ERR        0x4d
+#define UIV_EP13OUT          0x5d
+#define UIV_HCEP13IN         0x5d
+#define UIV_OUT13TOKEN       0x6d
+#define UIV_EP13PING         0x7d 
+
+#define UIV_HCOUT14ERR       0x1e
+#define UIV_EP14IN           0x2e
+#define UIV_HCEP14OUT        0x2e
+#define UIV_IN14TOKEN        0x3e
+#define UIV_HCIN14ERR        0x4e
+#define UIV_EP14OUT          0x5e
+#define UIV_HCEP14IN         0x5e
+#define UIV_OUT14TOKEN       0x6e
+#define UIV_EP14PING         0x7e 
+
+#define UIV_HCOUT15ERR       0x1f
+#define UIV_EP15IN           0x2f
+#define UIV_HCEP15OUT        0x2f
+#define UIV_IN15TOKEN        0x3f
+#define UIV_HCIN15ERR        0x4f
+#define UIV_EP15OUT          0x5f
+#define UIV_HCEP15IN         0x5f
+#define UIV_OUT15TOKEN       0x6f
+#define UIV_EP15PING         0x7f 
+
+
+/*ENDPRST*/
+#define ENDPRST_EPX(x)              ((x) & 0xf)
+#define ENDPRST_IO                  (1 << 4)
+#define ENDPRST_FIFORST             (1 << 5)
+#define ENDPRST_TOGRST              (1 << 6)
+#define ENDPRST_TOGRST_R            (0x3 << 6)
+/*bit 7 reserved*/
+
+/*USBCS*/
+/*bit 7 reserved*/
+#define	USBCS_DISCONN		        (1 << 6)
+#define	USBCS_SIGRSUME		        (1 << 5)
+#define	USBCS_HFMODE                (1 << 1)
+#define USBCS_LSMODE                (1 << 0)
+
+#if 0 /******** need to check bits. ***********************/
+/*FIFOCTRL*/
+/*bit 7:6 reserved*/
+#define FIFOCTRL_EPX(x)             ((x) & 0xf)
+#define	FIFOCTRL_FIFOAUTO	        (1 << 5)
+#define	FIFOCTRL_IO			        (1 << 4)
+
+#endif
+
+
+static void inline usb_writeb(u8 val, volatile void __iomem *reg)
+{
+	writeb(val, reg);
+}
+
+static void inline usb_writew(u16 val, volatile void __iomem *reg)
+{
+	writew(val, reg);
+}
+
+static void inline usb_writel(u32 val, volatile void __iomem *reg)
+{
+	writel(val, reg);
+}
+
+/******************************************************************************/
+static inline u8 usb_readb(volatile void __iomem *reg)
+{
+	return readb(reg);
+}
+
+static inline u16 usb_readw(volatile void __iomem *reg)
+{
+	return readw(reg);
+}
+
+static inline u32 usb_readl(volatile void __iomem *reg)
+{
+	return readl(reg);
+}
+
+/******************************************************************************/
+static void inline usb_setb(u8 val, volatile void __iomem *reg)
+{
+	//act_setb(val, (u32)reg);
+	writeb(readb(reg) | val, reg);
+}
+
+static void inline usb_setw(u16 val,volatile void __iomem *reg)
+{
+	//act_setw(val, (u32)reg);
+	writew(readw(reg) | val, reg);
+}
+
+static void inline usb_setl(u32 val,volatile void __iomem *reg)
+{
+	//act_setl(val, (u32)reg);
+	writel(readl(reg) | val, reg);
+}
+
+/******************************************************************************/
+static void inline usb_clearb(u8 val,volatile void __iomem *reg)
+{
+	//act_clearb(val, (u32)reg);
+	writeb(readb(reg)&(~val),reg);
+}
+
+static void inline usb_clearw(u16 val,volatile void __iomem *reg)
+{
+	//act_clearw(val, (u32)reg);
+	writew(readw(reg)&(~val),reg);
+}
+
+static void inline usb_clearl(u32 val,volatile void __iomem *reg)
+{
+	//act_clearl(val, (u32)reg);
+	writel(readl(reg)&(~val),reg);
+}
+
+/*********************** old define. *****************************************/
+
+static inline void usb_setbitsb(u8 mask, volatile void __iomem *mem)
+{
+	writeb(readb(mem) | mask, mem);
+}
+
+static inline void usb_setbitsw(u16 mask, volatile void __iomem *mem)
+{
+	writew(readw(mem) | mask, mem);
+}
+
+static inline void usb_setbitsl(ulong mask, volatile void __iomem *mem)
+{
+	writel(readl(mem) | mask, mem);
+}
+
+static inline void usb_clearbitsb(u8 mask, volatile void __iomem *mem)
+{
+	writeb(readb(mem) & ~mask, mem);
+}
+
+static inline void usb_clearbitsw(u16 mask, volatile void __iomem *mem)
+{
+	writew(readw(mem) & ~mask, mem);
+}
+
+static inline void usb_clearbitsl(ulong mask, volatile void __iomem *mem)
+{
+	writel(readl(mem) & ~mask, mem);
+}
+
+#endif  /* __AOTG_REGS_H__ */
+
diff --git a/drivers/usb/host/aotg_ring.c b/drivers/usb/host/aotg_ring.c
new file mode 100644
index 0000000..cea36b2
--- /dev/null
+++ b/drivers/usb/host/aotg_ring.c
@@ -0,0 +1,1509 @@
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+
+#include "aotg_hcd.h"
+#include "aotg_debug.h"
+#include "aotg_mon.h"
+
+void aotg_set_ring_linkaddr(struct aotg_ring *ring, u32 addr);
+int aotg_set_trb_as_ring_linkaddr(struct aotg_ring *ring, struct aotg_trb *trb);
+u32 ring_trb_virt_to_dma(struct aotg_ring *ring, 
+							struct aotg_trb *trb_vaddr);
+void clear_ring_irq(struct aotg_hcd *acthcd, unsigned int irq_mask);
+
+void aotg_dump_linklist_reg_2(struct aotg_hcd *acthcd, int dmanr)
+{
+	int is_out, index, index_multi;
+	
+	is_out = (dmanr & AOTG_DMA_OUT_PREFIX) ? 1 : 0;
+	index = dmanr & 0xf;
+	if (index >= 1) {
+		index_multi = index - 1;
+	} else {
+		ACT_HCD_ERR
+		return;
+	}
+
+	printk("--------- dma reg, ep%d-%s-------\n", index,
+			is_out ? "out" : "in");
+		
+	printk("HCDMABCKDOOR(0x%p) : 0x%x\n",
+		acthcd->base + HCDMABCKDOOR, readl(acthcd->base + HCDMABCKDOOR));
+	printk("HCDMAxOVERFLOWIRQ(0x%p) : 0x%x\n",
+		acthcd->base + HCDMAxOVERFLOWIRQ, readl(acthcd->base + HCDMAxOVERFLOWIRQ));
+	printk("HCDMAxOVERFLOWIEN(0x%p) : 0x%x\n",
+		acthcd->base + HCDMAxOVERFLOWIEN, readl(acthcd->base + HCDMAxOVERFLOWIEN));
+
+	if (is_out) {
+		printk("HCOUT%dDMALINKADDR(0x%p) : 0x%x\n", index,
+			acthcd->base + HCOUT1DMALINKADDR + index_multi * 0x10,
+			readl(acthcd->base + HCOUT1DMALINKADDR + index_multi * 0x10));
+		printk("HCOUT%dDMACURADDR(0x%p) : 0x%x\n",index,
+			acthcd->base + HCOUT1DMACURADDR + index_multi * 0x10,
+			readl(acthcd->base + HCOUT1DMACURADDR + index_multi * 0x10));
+		printk("HCOUT%dDMACTRL(0x%p) : 0x%x\n", index,
+			acthcd->base + HCOUT1DMACTRL + index_multi * 0x10,
+			readl(acthcd->base + HCOUT1DMACTRL + index_multi * 0x10));
+		printk("HCOUT%dDMACOMPLETECNT(0x%p) : 0x%x\n", index,
+			acthcd->base + HCOUT1DMACOMPLETECNT + index_multi * 0x10,
+			readl(acthcd->base + HCOUT1DMACOMPLETECNT + index_multi * 0x10));
+	} else {		
+		printk("HCIN%dDMALINKADDR(0x%p) : 0x%x\n", index,
+			acthcd->base + HCIN1DMALINKADDR+ index_multi * 0x10,
+			readl(acthcd->base + HCIN1DMALINKADDR+ index_multi * 0x10));
+		printk("HCIN%dDMACURADDR(0x%p) : 0x%x\n", index,
+			acthcd->base + HCIN1DMACURADDR + index_multi * 0x10,
+			readl(acthcd->base + HCIN1DMACURADDR + index_multi * 0x10));
+		printk("HCIN%dDMACTRL(0x%p) : 0x%x\n", index,
+			acthcd->base + HCIN1DMACTRL+ index_multi * 0x10,
+			readl(acthcd->base + HCIN1DMACTRL+ index_multi * 0x10));	
+		printk("HCIN%dDMACOMPLETECNT(0x%p) : 0x%x\n", index,
+			acthcd->base + HCIN1DMACOMPLETECNT + index_multi * 0x10,
+			readl(acthcd->base + HCIN1DMACOMPLETECNT + index_multi * 0x10));	
+	}
+}
+
+static void aotg_hcd_dump_trb(struct aotg_ring *ring, struct aotg_trb *trb)
+{
+	printk("trb:0x%x, dma:0x%x\n", (u32)trb, 
+		(u32)ring_trb_virt_to_dma(ring, trb));
+	printk("hw_buf_ptr : 0x%x\n", trb->hw_buf_ptr);
+	printk("hw_buf_len : %d\n", trb->hw_buf_len);
+	printk("hw_buf_remain : %d\n", trb->hw_buf_remain);
+	printk("hw_token : 0x%x\n", trb->hw_token);	
+}
+
+void aotg_hcd_dump_td(struct aotg_ring *ring, struct aotg_td *td)
+{
+	int i, j;
+	int num_trbs;	
+	struct aotg_trb *trb;
+
+	if (td == NULL){
+		ACT_HCD_ERR
+		return;
+	}
+	
+	num_trbs = td->num_trbs;
+	trb = td->trb_vaddr;
+
+	printk("==== dump td: %d trbs ====\n", td->num_trbs);
+	
+	if (trb + num_trbs > ring->last_trb) {
+		for (i = 0; trb + i < ring->last_trb + 1; i++) {
+			printk("trb_%d:\n", i);
+			aotg_hcd_dump_trb(ring, trb + i);												
+		}
+		trb = ring->first_trb;
+		j = 0;
+		for (; i < num_trbs; i++) {
+			printk("trb_%d:\n", i);
+			aotg_hcd_dump_trb(ring, trb + j);
+			j++;
+		}	
+	} else {
+		for (i = 0; i < num_trbs; i++) {
+			printk("trb_%d:\n", i);
+			aotg_hcd_dump_trb(ring, trb + i);
+		}
+	}
+	
+	printk("\n");
+
+	return;	
+}
+
+void inc_dequeue_safe(struct aotg_ring *ring)
+{
+	atomic_inc(&ring->num_trbs_free);
+	if (ring->dequeue_trb == ring->ring_trb) {
+		ring->dequeue_trb = ring->first_trb;
+	} else {
+		ring->dequeue_trb++;
+	}
+	return;
+}
+
+struct aotg_ring *aotg_alloc_ring(struct aotg_hcd *acthcd,
+				struct aotg_hcep *ep, unsigned int num_trbs, 
+				gfp_t mem_flags)
+{
+	dma_addr_t	dma;
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+	struct aotg_ring *ring;
+
+	ring = kmalloc(sizeof(struct aotg_ring), mem_flags);
+	if (!ring) {
+		return NULL;
+	}
+
+	ring->num_trbs = num_trbs;
+	if (num_trbs == 0) {
+		ACT_HCD_DBG
+		return ring;
+	}
+		
+	ring->first_trb = (struct aotg_trb *)
+					dma_alloc_coherent(dev,	num_trbs * sizeof(struct aotg_trb),
+					&dma, mem_flags);
+
+	HUB_DEBUG("frist_trb:%x,dma:%x\n",ring->first_trb,dma);
+	memset(ring->first_trb, 0, num_trbs * sizeof(struct aotg_trb));
+	//memset(ring->first_trb, 0, RING_SIZE);
+	ring->trb_dma = (u32)dma;
+	ring->last_trb = ring->first_trb + num_trbs - 1;
+	ring->ring_trb = ring->last_trb;
+	atomic_set(&ring->num_trbs_free, num_trbs);
+	ring->enqueue_trb = ring->first_trb;
+	ring->dequeue_trb = ring->first_trb;
+
+	ring->is_running = 0;
+	ring->is_out = ep->is_out ? 1 : 0;
+	ring->intr_inited = 0;
+	ring->intr_started = 0;
+	ring->priv = ep;
+	ring->mask = ep->mask;
+	ring->type = ep->type;
+	ring->enring_cnt = 0;
+	ring->dering_cnt = 0;
+	ring->ring_stopped= 0;
+
+	ring->reg_dmalinkaddr = GET_DMALINKADDR_REG(ring->is_out, acthcd->base + HCOUT1DMALINKADDR,
+								acthcd->base + HCIN1DMALINKADDR, ep->index);
+	ring->reg_curaddr = GET_CURADDR_REG(ring->is_out, acthcd->base + HCOUT1DMACURADDR,
+								acthcd->base + HCIN1DMACURADDR, ep->index);
+	ring->reg_dmactrl = GET_DMACTRL_REG(ring->is_out, acthcd->base + HCOUT1DMACTRL,
+								acthcd->base + HCIN1DMACTRL, ep->index);
+	ring->reg_dmacomplete_cnt = GET_DMACOMPLETE_CNT_REG(ring->is_out, 
+								acthcd->base + HCOUT1DMACOMPLETECNT,
+								acthcd->base + HCIN1DMACOMPLETECNT, ep->index);
+
+
+	/*printk("=====================================\n");
+		
+	printk("first_trb:0x%x,last_trb:0x%x, ring_trb:0x%x\n",
+			(u32)(ring->first_trb), (u32)(ring->last_trb), (u32)(ring->ring_trb));
+
+	printk("enq_trb:0x%x, deq_trb:0x%x\n",
+			(u32)(ring->enqueue_trb), (u32)(ring->dequeue_trb));
+	printk("=====================================\n");*/
+	return ring;
+}
+
+void aotg_free_ring(struct aotg_hcd *acthcd, struct aotg_ring *ring)
+{
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+	if (!ring) {
+		return;
+	}
+
+	dma_free_coherent(dev, ring->num_trbs * sizeof(struct aotg_trb),
+			ring->first_trb, ring->trb_dma);
+	kfree(ring);
+	return;
+}
+
+struct aotg_td *aotg_alloc_td(gfp_t mem_flags)
+{
+	struct aotg_td *td;
+
+	//td = kmalloc(sizeof(struct aotg_td), mem_flags);	
+	td = kmalloc(sizeof(struct aotg_td), GFP_ATOMIC);
+	if (!td) {
+		return NULL;
+	}
+	memset(td, 0, sizeof(struct aotg_td));
+
+	td->cross_ring = 0;
+	td->err_count = 0;
+	td->urb = NULL;
+	INIT_LIST_HEAD(&td->queue_list);
+	INIT_LIST_HEAD(&td->enring_list);
+	INIT_LIST_HEAD(&td->dering_list);	
+
+	return td;
+}
+
+void aotg_release_td(struct aotg_td *td)
+{
+	if (!td)
+		return;
+	kfree(td);
+}
+
+void enable_overflow_irq(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	u8 mask = ep->mask;
+	u8 is_out = mask & USB_HCD_OUT_MASK;
+	u8 ep_num = mask & 0x0f;
+
+	if (is_out) {
+		usb_setbitsl(1 << (ep_num + 16), acthcd->base + HCDMAxOVERFLOWIEN);
+	} else {
+		usb_setbitsl(1 << ep_num, acthcd->base + HCDMAxOVERFLOWIEN);
+	}
+	return;
+}
+
+void disable_overflow_irq(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	u8 mask = ep->mask;
+	u8 is_out = mask & USB_HCD_OUT_MASK;
+	u8 ep_num = mask & 0x0f;
+
+	if (is_out) {
+		usb_clearbitsl(1 << (ep_num + 16), acthcd->base + HCDMAxOVERFLOWIEN);
+	} else {
+		usb_clearbitsl(1 << ep_num, acthcd->base + HCDMAxOVERFLOWIEN);
+	}
+	return;
+}
+
+void clear_overflow_irq(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	u8 mask = ep->mask;
+	u8 is_out = mask & USB_HCD_OUT_MASK;
+	u8 ep_num = mask & 0x0f;
+
+	if (is_out) {
+		usb_clearbitsl(1 << (ep_num + 16), acthcd->base + HCDMAxOVERFLOWIRQ);
+	} else {		
+		usb_clearbitsl(1 << ep_num, acthcd->base + HCDMAxOVERFLOWIRQ);
+	}
+}
+
+// FIXME
+void overflow_irq_handler(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	struct aotg_ring *ring;
+	
+	if (!ep) {
+		printk(KERN_ERR"%s, ep%d is NULL!\n", __FUNCTION__, ep->index);
+		return;
+	}
+
+	ring = ep->ring;
+
+	return;
+}
+/*
+void aotg_handle_overflow_irq(struct aotg_hcd *acthcd)
+{
+	int i;
+	unsigned int irq_pend = 0;
+	struct aotg_hcep *ep;
+
+	irq_pend = readl(acthcd->base + HCDMAxOVERFLOWIRQ);
+
+	if (irq_pend & RING_IN_OF) {
+		for (i = 1; i < 16; i++) {
+			if (irq_pend & (0x1 << i)) {
+				ep = acthcd->inep[i];
+ 				overflow_irq_handler(acthcd, ep);
+			}
+		}
+	}
+
+	if (irq_pend & RING_OUT_OF) {
+		for (i = 1; i < 16; i++) {
+			if (irq_pend & (0x1 << (i + 16))) {
+				ep = acthcd->outep[i];
+ 				overflow_irq_handler(acthcd, ep);
+			}	
+	}
+
+	writel(irq_pend, acthcd->base + HCDMAxOVERFLOWIRQ); 		
+}
+*/
+int is_ring_running(struct aotg_ring *ring)
+{
+	return (readl(ring->reg_dmactrl) & 0x1) ? 1 : 0;
+}
+
+void aotg_start_ring(struct aotg_ring *ring, u32 addr)
+{
+	struct aotg_trb *temp_trb = ring->dequeue_trb;
+	int i;
+	if ((ring->type == PIPE_BULK) && ((temp_trb->hw_token & TRB_OF)== 0)) {
+		for (i=0; i< NUM_TRBS; i++) {
+			if (temp_trb->hw_token == 0xaa) { /*deal dequeue urb*/
+				inc_dequeue_safe(ring);
+				memset(temp_trb,0,sizeof(struct aotg_trb));
+			}
+			else if (temp_trb->hw_token & TRB_OF) {
+				break;
+			}
+			
+			if (temp_trb == ring->last_trb) {
+				temp_trb= ring->first_trb;
+			}
+			else {
+				temp_trb++;
+			}
+		}
+		addr = ring_trb_virt_to_dma(ring, temp_trb);
+	}
+	aotg_set_ring_linkaddr(ring, addr);
+	mb();
+	writel(DMACTRL_DMACS,ring->reg_dmactrl);
+
+}
+
+void aotg_stop_ring(struct aotg_ring *ring)
+{
+	writel(DMACTRL_DMACC, ring->reg_dmactrl);
+}
+
+void aotg_pause_ring(struct aotg_ring *ring)
+{
+	usb_setbitsl(DMACTRL_DMACC, ring->reg_dmactrl);			
+}
+
+#if(0)
+void aotg_stop_ring(struct aotg_hcd *acthcd, struct aotg_hcep *ep)
+{
+	writel(DMACTRL_DMACC,ep->ring->reg_dmactrl);
+	usb_clearbitsb(0x80, ep->reg_hcepcon);
+	usb_settoggle(ep->udev, ep->epnum, ep->is_out, 0);
+	aotg_hcep_reset(acthcd, ep->mask, ENDPRST_FIFORST);
+	writeb(ep->epnum, ep->reg_hcepctrl);
+	usb_setbitsb(0x80, ep->reg_hcepcon);
+}
+#endif
+
+u32 ring_trb_virt_to_dma(struct aotg_ring *ring, 
+							struct aotg_trb *trb_vaddr)
+{
+	u32 addr;
+	
+	unsigned long offset;
+
+	if (!ring || !trb_vaddr) {
+		return 0;
+	}
+
+	if (trb_vaddr > ring->last_trb) {
+		return 0;
+	}
+
+	offset = trb_vaddr - ring->first_trb;
+	//return ring->trb_dma + (offset * sizeof(*trb_vaddr));
+	addr = ring->trb_dma + (offset * sizeof(*trb_vaddr));
+	
+	//addr = (u32)virt_to_phys(trb_vaddr);
+	//printk("---out:%d,offset:%ld, trb:0x%x,addr:0x%x------\n",ring->is_out,offset, 
+	//		trb_vaddr, addr);
+	return addr;
+	
+}
+
+void aotg_set_ring_linkaddr(struct aotg_ring *ring, u32 addr)
+{
+	if (!ring) {
+		ACT_HCD_ERR
+		return;
+	}
+	writel(addr, ring->reg_dmalinkaddr);
+
+	//printk("linkaddr(0x%p):0x%x\n", ring->reg_dmalinkaddr,
+	//		readl(ring->reg_dmalinkaddr));
+}
+
+int aotg_set_trb_as_ring_linkaddr(struct aotg_ring *ring, struct aotg_trb *trb)
+{
+	u32 addr;
+
+	addr = (u32)ring_trb_virt_to_dma(ring, trb);
+	if (!addr) {
+		ACT_HCD_ERR
+		return -1;
+	}
+	
+	aotg_set_ring_linkaddr(ring, addr);
+	return 0;
+}
+
+int ring_empty(struct aotg_ring *ring)
+{
+	return (atomic_read(&ring->num_trbs_free) == NUM_TRBS) ? 1 : 0;
+}
+
+int ring_full(struct aotg_ring *ring)
+{
+	return (atomic_read(&ring->num_trbs_free) == 0) ? 1 : 0;
+}
+
+inline int is_room_on_ring(struct aotg_ring *ring, unsigned int num_trbs)
+{
+	return (num_trbs > atomic_read(&ring->num_trbs_free)) ? 0 : 1;
+}
+
+inline unsigned int	count_urb_need_trbs(struct urb *urb)
+{
+	int num_sgs, num_trbs;
+	/* at least one trb */
+	num_sgs = urb->num_mapped_sgs;
+	if (num_sgs == 0) {
+		num_trbs = 1;
+	} else {
+		num_trbs = num_sgs;
+	}
+		
+	if (usb_pipeout(urb->pipe) && 
+			(urb->transfer_flags & URB_ZERO_PACKET)) {
+		num_trbs++;
+	}
+
+	return num_trbs;
+}
+
+void aotg_fill_trb(struct aotg_trb *trb,
+					u32 dma_addr, u32 len, u32 token)
+{
+	trb->hw_buf_ptr = dma_addr;
+	trb->hw_buf_len = len;
+	trb->hw_token = token;
+
+	ACT_LINKLIST_DMA_DEBUG("hw_ptr(0x%x), hw_len(%d),hw_token(0x%x)\n",
+			trb->hw_buf_ptr, trb->hw_buf_len, trb->hw_token);
+	return;
+}
+
+int aotg_sg_map_trb(struct aotg_trb *trb, 
+						struct scatterlist *sg, int len, u32 token) 
+{
+	int this_trb_len;
+
+	if (NULL == sg) {
+		aotg_fill_trb(trb, 0, 0, token);
+		return 0;
+	}
+
+	this_trb_len = min_t(int, sg_dma_len(sg), len);
+
+	aotg_fill_trb(trb, (u32)sg_dma_address(sg), this_trb_len, token);
+
+	return this_trb_len;
+}
+#if (0)
+/*
+ * ring->enqueue_trb should be overflow
+ */
+void inc_enqueue_safe(struct aotg_ring *ring)
+{
+	atomic_dec(&ring->num_trbs_free);
+	if (ring->enqueue_trb == ring->ring_trb) {
+		if (ring->type == PIPE_BULK) {
+			ring->enqueue_trb->hw_token &= ~TRB_CHN;
+			if (ring->is_out)			
+				ring->enqueue_trb->hw_token |= TRB_ITE | TRB_LT;
+			else 		
+				ring->enqueue_trb->hw_token |= TRB_ICE | TRB_LT;
+			ring->enqueue_trb = ring->first_trb;
+		} else {
+			ring->enqueue_trb->hw_token |= TRB_COF;
+			ring->enqueue_trb = ring->first_trb;
+		}
+	} else {
+		ring->enqueue_trb += 1;
+	}
+}
+#endif
+void enqueue_trb(struct aotg_ring *ring, u32 buf_ptr, u32 buf_len,
+				u32 token)
+{
+	struct aotg_trb *trb;
+	trb = ring->enqueue_trb;
+
+	atomic_dec(&ring->num_trbs_free);
+	if (trb == ring->last_trb) {
+		if (ring->type == PIPE_BULK) {
+			token &= ~TRB_CHN;
+			if (ring->is_out)
+				token |= TRB_ITE | TRB_LT;
+			else
+				token |= TRB_ICE | TRB_LT;
+			ring->enqueue_trb = ring->first_trb;
+		} else {
+			token |= TRB_COF;
+			ring->enqueue_trb = ring->first_trb;
+		}
+	} else {
+		ring->enqueue_trb += 1;
+	}
+
+	trb->hw_buf_ptr = buf_ptr;
+	trb->hw_buf_len = buf_len;
+	trb->hw_buf_remain = 0;
+	wmb();
+	trb->hw_token = token;
+}
+
+/*
+ * ensure ring has enough room for this td 
+ * before call this function.
+ */
+int ring_enqueue_sg_td(struct aotg_hcd *acthcd,
+				struct aotg_ring *ring, struct aotg_td *td)
+{
+	u8 is_out;
+	int num_sgs, num_trbs;
+	int len, this_trb_len;
+	u32 addr, token;
+	struct urb *urb = td->urb;
+	struct scatterlist *sg;
+
+	is_out = usb_pipeout(urb->pipe);
+
+	len = urb->transfer_buffer_length;
+	num_sgs = urb->num_mapped_sgs;	
+	num_trbs = count_urb_need_trbs(urb);
+
+	td->num_trbs = num_trbs;
+	td->trb_vaddr = ring->enqueue_trb;
+	td->trb_dma= ring_trb_virt_to_dma(ring, ring->enqueue_trb);
+
+	if (td->trb_vaddr + (num_trbs - 1) > ring->last_trb) {
+		td->cross_ring = 1;
+	}
+
+	sg = urb->sg;
+	addr = (u32)sg_dma_address(sg);
+	this_trb_len = (u32)min_t(int, sg_dma_len(sg), len);
+
+	if (is_out) 
+		token = TRB_OF;
+	else 
+		//token = TRB_CSP | TRB_ISE | TRB_IZE | TRB_OF;		
+		token = TRB_CSP | TRB_OF;
+				
+	do {
+		if (num_trbs == 1) {		
+			token &= ~TRB_CHN;
+			if (is_out) 
+				token |= TRB_ITE;
+			else 
+				token |= TRB_ICE;
+			
+			if (is_out && (urb->transfer_flags & URB_ZERO_PACKET)) 
+				enqueue_trb(ring, 0, 0, token);
+		 	else 
+				enqueue_trb(ring, addr, this_trb_len, token);
+			break;			
+		}
+		token |= TRB_CHN;
+		enqueue_trb(ring, addr, this_trb_len, token);
+		len -= this_trb_len;
+		num_trbs--;
+		num_sgs--;
+
+		if (num_sgs) {
+			sg = sg_next(sg);
+			addr = (u32)sg_dma_address(sg);
+			this_trb_len = (u32)min_t(int, sg_dma_len(sg), len);
+		}
+	} while (num_trbs);
+
+	//aotg_hcd_dump_td(ring, td);
+
+	return 0;
+}
+
+int aotg_ring_enqueue_td(struct aotg_hcd *acthcd, 
+				struct aotg_ring *ring, struct aotg_td *td)
+{
+	u8 is_out;
+	u32 addr, token, this_trb_len;
+	int num_trbs;
+	struct urb *urb = td->urb;
+
+	if (!acthcd || !td || !ring || !urb) {
+		ACT_HCD_ERR
+		return -1;
+	}
+	
+	num_trbs = count_urb_need_trbs(urb);
+
+	if (!is_room_on_ring(ring, num_trbs)) {
+		//ACT_HCD_DBG
+		return -1;
+	}
+
+	if (urb->num_sgs) {
+		return ring_enqueue_sg_td(acthcd, ring, td);		
+	}
+	
+	is_out = usb_pipeout(urb->pipe);
+	
+	td->num_trbs = num_trbs;
+	td->trb_vaddr = ring->enqueue_trb;
+	td->trb_dma = ring_trb_virt_to_dma(ring, ring->enqueue_trb);
+	
+	addr = (u32)urb->transfer_dma;
+	this_trb_len = (u32)urb->transfer_buffer_length;
+
+	if (is_out) {
+		token = TRB_OF;
+	} else {
+		token = TRB_CSP | TRB_OF;
+	}
+
+	/*
+	 * Finish bulk OUT with short packet	
+	 */
+	if (num_trbs > 1) {
+		token |= TRB_CHN;
+		enqueue_trb(ring, addr, this_trb_len, token);
+		addr = 0;
+		this_trb_len = 0;
+	}
+	
+	token &= ~TRB_CHN;
+	if (!port_host_plug_detect[acthcd->id])
+		token |= TRB_LT; /*8723bu,release cpu for interrupt transfer*/
+	if (is_out)	
+		token |= TRB_ITE;
+	else 
+		token |= TRB_ICE;
+
+	enqueue_trb(ring, addr, this_trb_len, token);
+	
+	//aotg_hcd_dump_td(ring, td);
+	
+	return 0;
+}
+
+void aotg_reorder_intr_td( struct aotg_hcep *ep) {
+	struct aotg_td *td, *next, *entry_td = NULL;
+	struct urb *urb;
+	struct aotg_ring *ring;
+	unsigned long td_temp = ULONG_MAX;
+	ring = ep->ring;
+	
+	ring->dequeue_trb = ring->first_trb;
+	ring->enqueue_trb = ring->first_trb;
+	list_for_each_entry(td, &ep->enring_td_list, enring_list) {
+		if (td_temp > (unsigned long)(td->intr_mem_vaddr)) {
+			td_temp = (unsigned long)(td->intr_mem_vaddr);
+			entry_td = td;
+		}
+	}
+	
+	list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+		if ((unsigned long)(td->intr_mem_vaddr) > td_temp) {
+			if (td->urb) {
+				urb = td->urb;
+				td->urb = NULL;
+				entry_td->urb = urb;
+				entry_td = list_entry(entry_td->enring_list.next,struct aotg_td,enring_list);
+			}
+			list_del(&td->enring_list);
+			list_add_tail(&td->enring_list, &ep->enring_td_list);
+		}
+		else {
+			break;
+		}
+	}
+}
+
+void aotg_reorder_iso_td(struct aotg_hcd *acthcd, struct aotg_ring *ring) {
+	struct aotg_td *td, *next;
+	struct aotg_trb *new_trb_q, *prev_trb_q, *trb;
+	int i;
+	dma_addr_t dma, prev_dma;
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+	struct aotg_hcep *ep = (struct aotg_hcep *)ring->priv;
+
+	new_trb_q = (struct aotg_trb *)
+		dma_alloc_coherent(dev,	NUM_TRBS * sizeof(struct aotg_trb),
+		&dma, GFP_ATOMIC);
+	if (!new_trb_q) {
+		pr_err("dma_alloc_coherent trb error!!!\n" );
+		return;
+	}
+	memset(new_trb_q, 0, NUM_TRBS * sizeof(struct aotg_trb));
+	prev_trb_q = ring->first_trb;
+	ring->first_trb = new_trb_q;
+	prev_dma = ring->trb_dma;
+	ring->trb_dma = (u32)dma;
+	ring->last_trb = ring->first_trb + NUM_TRBS - 1;
+	ring->ring_trb = ring->last_trb;
+	atomic_set(&ring->num_trbs_free, NUM_TRBS);
+	ring->enqueue_trb = ring->first_trb;
+	ring->dequeue_trb = ring->first_trb;
+
+	list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+		if (td) {
+			trb = td->trb_vaddr;
+			td->trb_vaddr = ring->enqueue_trb;
+			td->trb_dma = ring_trb_virt_to_dma(ring, ring->enqueue_trb);
+			for (i = 0; i < td->num_trbs; i++) {
+				enqueue_trb(ring, trb->hw_buf_ptr, trb->hw_buf_len, trb->hw_token &(~TRB_COF));
+			}
+		}
+	}
+	dma_free_coherent(dev, NUM_TRBS * sizeof(struct aotg_trb), prev_trb_q, prev_dma);
+}
+
+int aotg_ring_enqueue_intr_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, 
+						struct aotg_hcep *ep, struct urb *urb, gfp_t mem_flags)
+{
+	u8 is_out;
+	u32 addr, token, this_trb_len;
+	int i;
+	int mem_size;
+	dma_addr_t	dma;
+	struct aotg_td *td, *next;
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+
+	if (!is_room_on_ring(ring, INTR_TRBS)) {
+		printk("%s err, check it!\n", __FUNCTION__);
+		return -1;
+	}
+
+	is_out = usb_pipeout(urb->pipe);
+	//mem_size = max(urb->transfer_buffer_length,usb_maxpacket(ep->udev, urb->pipe, is_out));
+	mem_size = urb->transfer_buffer_length;
+	//printk("====ep:%p,mem_size:%d...........====\n",ep,mem_size);
+	ring->intr_mem_size = mem_size;
+	ring->intr_dma_buf_vaddr = (u8 *)dma_alloc_coherent(dev, mem_size * INTR_TRBS, 
+		&dma, mem_flags);
+	if (!ring->intr_dma_buf_vaddr) {
+		printk("%s err, alloc dma buf for intr fail!\n", __FUNCTION__);
+		return -1;
+	}
+	ring->intr_dma_buf_phyaddr = dma;
+	//printk("dma_buf_vaddr:0x%p, dma_buf_phyaddr:0x%x\n",
+	//		ring->intr_dma_buf_vaddr, (u32)ring->intr_dma_buf_phyaddr);
+
+	for (i = 0; i < INTR_TRBS; i++) {
+		td = aotg_alloc_td(mem_flags);
+		if (!td) {
+			printk("%s err, alloc td fail\n", __FUNCTION__);
+			goto fail;
+		}
+		td->intr_mem_vaddr = ring->intr_dma_buf_vaddr + mem_size * i;
+		td->intr_men_phyaddr = ring->intr_dma_buf_phyaddr + mem_size * i;
+		//td->intr_mem_phyaddr = virt_to_phys(td->intr_mem_vaddr);
+		memset(td->intr_mem_vaddr, 0, mem_size);
+//		printk("buf_%d  virt_addr:0x%p, phy_addr:0x%x, size:%d\n",
+//				i, td->intr_mem_vaddr, (u32)td->intr_men_phyaddr, mem_size);
+		
+		td->num_trbs = 1;
+		td->trb_vaddr = ring->enqueue_trb;
+		td->trb_dma = ring_trb_virt_to_dma(ring, ring->enqueue_trb);
+
+		this_trb_len = mem_size;
+		if (is_out) {
+			token = TRB_OF | TRB_ITE | TRB_LT;
+			enqueue_trb(ring, urb->transfer_dma, this_trb_len, token);
+		}	else {
+			token = TRB_OF | TRB_ICE | TRB_CSP;
+			addr = (u32)td->intr_men_phyaddr;
+			enqueue_trb(ring, addr, this_trb_len, token);
+		}
+
+
+		list_add_tail(&td->enring_list, &ep->enring_td_list);
+		ring->enring_cnt++;
+	}
+
+	ring->intr_inited = 1;
+	return 0;
+
+fail:
+	list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+		aotg_release_td(td);
+	}
+	
+	dma_free_coherent(dev, ring->intr_mem_size * INTR_TRBS,
+				ring->intr_dma_buf_vaddr, ring->intr_dma_buf_phyaddr);
+
+	return -1;
+}
+
+int aotg_intr_get_finish_trb(struct aotg_ring *ring)
+{
+	int i,count = 0;
+	struct aotg_trb *trb = ring->first_trb;
+	
+	for (i=0; i<INTR_TRBS; i++) {
+		if ((trb->hw_token&TRB_OF) == 0) {
+			count++;
+		}
+		trb++;
+	}
+	return count;
+}
+
+int aotg_intr_chg_buf_len(struct aotg_hcd *acthcd, struct aotg_ring *ring, int len)
+{
+	struct aotg_td *td;
+	dma_addr_t	dma;
+	int i = 0;
+	u32 token;
+	struct aotg_hcep *ep = (struct aotg_hcep *)ring->priv;
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+	//aotg_stop_ring(ring);
+	writel(DMACTRL_DMACC,ring->reg_dmactrl);
+	usb_clearbitsb(0x80, ep->reg_hcepcon);
+	usb_settoggle(ep->udev, ep->epnum, ep->is_out, 0);
+	aotg_hcep_reset(acthcd, ep->mask, ENDPRST_FIFORST);
+	writeb(ep->epnum, ep->reg_hcepctrl);
+	usb_setbitsb(0x80, ep->reg_hcepcon);
+
+	dma_free_coherent(dev, ring->intr_mem_size * INTR_TRBS,
+			ring->intr_dma_buf_vaddr, ring->intr_dma_buf_phyaddr);
+
+	ring->intr_mem_size = len;
+	ring->intr_dma_buf_vaddr = (u8 *)dma_alloc_coherent(dev, len * INTR_TRBS, 
+		&dma, GFP_ATOMIC);
+	if (!ring->intr_dma_buf_vaddr) {
+		printk("%s err, alloc dma buf for intr fail!\n", __FUNCTION__);
+		return -1;
+	}
+	ring->intr_dma_buf_phyaddr = dma;
+	
+	aotg_reorder_intr_td(ep);
+	list_for_each_entry(td, &ep->enring_td_list, enring_list) {
+		td->intr_mem_vaddr = ring->intr_dma_buf_vaddr + len * i;
+		td->intr_men_phyaddr = ring->intr_dma_buf_phyaddr + len * i;
+		memset(td->intr_mem_vaddr, 0, len);
+		
+		if (ring->is_out) 
+			token = TRB_OF | TRB_ITE | TRB_LT;
+		else 
+			token = TRB_OF | TRB_ICE | TRB_CSP;	
+
+		enqueue_trb(ring, td->intr_men_phyaddr, len, token);
+		i++;
+	}
+	mb();
+	writel(DMACTRL_DMACS,ep->ring->reg_dmactrl);
+	
+	return 0;
+}
+
+void aotg_intr_dma_buf_free(struct aotg_hcd *acthcd, struct aotg_ring *ring)
+{
+	struct aotg_td *td, *next;
+	struct aotg_hcep *ep = (struct aotg_hcep *)ring->priv;
+	struct device *dev = aotg_to_hcd(acthcd)->self.controller;
+
+	list_for_each_entry_safe(td, next, &ep->enring_td_list, enring_list) {
+		aotg_release_td(td);
+	}
+
+	dma_free_coherent(dev, ring->intr_mem_size * INTR_TRBS,
+			ring->intr_dma_buf_vaddr, ring->intr_dma_buf_phyaddr);
+}
+
+int aotg_ring_enqueue_isoc_td(struct aotg_hcd *acthcd, 
+				struct aotg_ring *ring, struct aotg_td *td)
+{
+	u8 is_out;
+	u32 start_addr;
+	u32 addr, token, this_trb_len;
+	int i = 0;
+	int start_frame;
+	int num_trbs;
+	struct urb *urb = td->urb;
+
+	if (!acthcd || !td || !ring || !urb) {
+		ACT_HCD_ERR
+		return -1;
+	}	
+
+	num_trbs = urb->number_of_packets;
+	if (unlikely(num_trbs == 0)) {
+		ACT_HCD_ERR
+		return -1;
+	}
+	
+	if (unlikely(!is_room_on_ring(ring, num_trbs))) {
+		ACT_HCD_DBG
+		return -1;
+	}	
+	
+	is_out = usb_pipeout(urb->pipe);
+	
+	td->num_trbs = num_trbs;
+	td->trb_vaddr = ring->enqueue_trb;
+	td->trb_dma = ring_trb_virt_to_dma(ring, ring->enqueue_trb);
+
+	start_frame = readw(acthcd->base + HCFRMNRL);
+	start_frame &= 0x3fff;
+	urb->start_frame = start_frame;
+	
+	start_addr = (u32)urb->transfer_dma;
+	
+	if (is_out) {
+		token = TRB_OF;
+	} else {
+		token = TRB_CSP | TRB_OF;
+	}
+
+	do {
+		addr = start_addr + urb->iso_frame_desc[i].offset;
+		this_trb_len = urb->iso_frame_desc[i].length;
+		if (num_trbs == 1) {
+			token &= ~TRB_CHN;
+			if (is_out)	
+				token |= TRB_ITE;
+			else 
+				token |= TRB_ICE;
+			
+			enqueue_trb(ring, addr, this_trb_len, token);
+			break;
+		}
+		enqueue_trb(ring, addr, this_trb_len, token);
+		i++;
+		num_trbs--;
+	} while(num_trbs);
+	
+	return 0;
+}
+
+void dequeue_td(struct aotg_ring *ring, struct aotg_td *td, int dequeue_flag)
+{
+	int i,num_trbs;
+	struct aotg_trb *trb;
+
+	if (!ring || !td || ((struct list_head *)(&td->enring_list)->next == LIST_POISON1)) {
+		ACT_HCD_ERR
+		return;
+	}
+	trb = td->trb_vaddr;
+	num_trbs = td->num_trbs;
+	for (i = 0; i < num_trbs; i++) {
+		if (dequeue_flag != TD_IN_RING) {
+			inc_dequeue_safe(ring);
+			memset(trb,0,sizeof(struct aotg_trb));
+		}
+		else {
+		 /*perhaps the dequeue urb in the middle of queue_list,don't change ring->dequeue here*/
+			trb->hw_token = 0xaa;
+		}
+		if (trb == ring->last_trb) {
+			trb = ring->first_trb;
+		}
+		else {
+			trb++;
+		}
+	}
+	list_del(&td->enring_list);
+	aotg_release_td(td);
+	ring->dering_cnt++;
+}
+
+void dequeue_intr_td(struct aotg_ring *ring, struct aotg_td *td)
+{
+	u32 addr, token, this_trb_len;
+	struct aotg_trb *trb;
+	struct aotg_hcep *ep;
+
+	if (!ring || !td) {
+		ACT_HCD_ERR
+		return;
+	}
+
+	trb = td->trb_vaddr;
+	inc_dequeue_safe(ring);
+	list_del(&td->enring_list);
+	ring->dering_cnt++;
+
+	td->urb = NULL;
+	memset(td->intr_mem_vaddr, 0, ring->intr_mem_size);
+
+	if (ring->is_out) 
+		token = TRB_OF | TRB_ITE | TRB_LT;
+	else 
+		token = TRB_OF | TRB_ICE | TRB_CSP;	
+	this_trb_len = ring->intr_mem_size;	
+	addr = (u32)td->intr_men_phyaddr;
+
+	ep = (struct aotg_hcep *)ring->priv;
+	enqueue_trb(ring, addr, this_trb_len, token);
+	list_add_tail(&td->enring_list, &ep->enring_td_list);
+	ring->enring_cnt++;	
+	return;
+}
+
+#if (1)
+int aotg_ring_dequeue_intr_td(struct aotg_hcd *acthcd, struct aotg_hcep *ep,
+		struct aotg_ring *ring,	struct aotg_td *td)
+{
+	u32 addr;
+	struct aotg_td *td_tmp;
+
+	/*To INTR transfer: first dequeue happens at the last step of insertion
+	  while there isn't any data transmission, so we just empty the urb of
+	  the first td but	don't dequeue the td.*/
+	//     aotg_stop_ring(ring);
+	if (td->trb_vaddr->hw_token & TRB_OF)
+		td->urb = NULL;
+	else
+		dequeue_intr_td(ring, td);
+
+	td_tmp = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+	if ((td_tmp) && (td_tmp->urb)) {
+		printk("%s, unormal circumstances, pls check it...\n", __FUNCTION__);
+		printk("restart ep%d intr ring\n", ep->index);
+		addr = ring_trb_virt_to_dma(ring, ring->dequeue_trb);
+		aotg_start_ring(ring, addr);
+	}
+	return 0;
+}
+#else
+int aotg_ring_dequeue_intr_td(struct aotg_hcd *acthcd, struct aotg_hcep *ep,
+			struct aotg_ring *ring,	struct aotg_td *td)
+{
+	struct aotg_trb *trb;
+	trb = td->trb_vaddr;
+	
+	writel(DMACTRL_DMACC,ep->ring->reg_dmactrl);
+	usb_clearbitsb(0x80, ep->reg_hcepcon);
+	usb_settoggle(ep->udev, ep->epnum, ep->is_out, 0);
+	aotg_hcep_reset(acthcd, ep->mask, ENDPRST_FIFORST);
+	writeb(ep->epnum, ep->reg_hcepctrl);
+	usb_setbitsb(0x80, ep->reg_hcepcon);
+	
+	td->urb = NULL;
+	mb();
+	trb->hw_token |= TRB_OF;
+	trb->hw_token &= ~(AOTG_TRB_IOC|AOTG_TRB_IOZ|AOTG_TRB_IOS);
+	aotg_reorder_intr_td(ep);
+
+	/*td_tmp = list_first_entry(&ep->enring_td_list, struct aotg_td, enring_list);
+	if (td_tmp->urb) {
+		printk("%s, unormal circumstances, pls check it...\n", __FUNCTION__);
+		printk("restart ep%d intr ring\n", ep->index);
+		addr = ring_trb_virt_to_dma(ring, ring->dequeue_trb);
+		aotg_start_ring(ring, addr);		
+	}*/
+
+	return 0;
+}
+#endif
+
+int aotg_ring_dequeue_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, 
+			struct aotg_td *td, int dequeue_flag)
+{
+	int index;
+	struct aotg_hcep *ep;
+	struct urb *urb = td->urb;
+	td->urb = NULL;
+	//u32 addr;
+	
+	//u32 ring_curaddr;
+
+	//ring_curaddr = readl(ring->reg_curaddr);
+
+	//aotg_hcd_dump_td(ring, td);
+
+	if (dequeue_flag == TD_IN_QUEUE) {
+		/*
+	 	 * must hold the spin_lock_irq, prevent td will be enqueue in ep->enring_list
+	 	 * in interrupt contex
+	 	 */
+		list_del(&td->queue_list);
+		aotg_release_td(td);
+		//ACT_HCD_DBG
+		return 0;
+	} else if (dequeue_flag == TD_IN_RING) {
+		//if (ring_curaddr < td->trb_dma || 
+		//	ring_curaddr > ring_trb_virt_to_dma(ring, td->trb_vaddr + td->num_trbs -1)) {
+		//	printk(KERN_ERR"%s, unknow situation!\n", __FUNCTION__);
+		//}
+		ep = (struct aotg_hcep *)urb->ep->hcpriv;
+		//aotg_stop_ring(ring);
+		writel(DMACTRL_DMACC,ep->ring->reg_dmactrl);
+		usb_clearbitsb(0x80, ep->reg_hcepcon);
+		usb_settoggle(ep->udev, ep->epnum, ep->is_out, 0);
+		aotg_hcep_reset(acthcd, ep->mask, ENDPRST_FIFORST);
+		writeb(ep->epnum, ep->reg_hcepctrl);
+		usb_setbitsb(0x80, ep->reg_hcepcon);
+		/*
+		 * dequeue urb, when the urb complete in hardware contex
+		 */
+		index = ring->mask & 0xf;		
+		if ((0x1 << index) & (readw(acthcd->base + HCINxDMAIRQ0)) ||
+			(0x1 << index) & (readw(acthcd->base + HCOUTxBUFEMPTYIRQ0))) {
+			printk("noticd:%s, IN%dIRQ:0x%x; OUT%dIRQ:0x%x\n",
+					__FUNCTION__, index, readw(acthcd->base + HCINxDMAIRQ0),
+					index, readw(acthcd->base + HCOUTxBUFEMPTYIRQ0));
+			clear_ring_irq(acthcd, ring->mask);
+		}
+		
+		dequeue_td(ring, td, dequeue_flag);	
+		//ACT_HCD_DBG
+		/*
+		 * need restart the remain td in the ring or wait to be dequeue ?
+		 */
+		/*if (!ring_empty(ring)) {
+			addr = ring_trb_virt_to_dma(ring, ring->dequeue_trb);
+			aotg_start_ring(ring, addr);
+			//ACT_HCD_DBG
+		}*/
+	}
+
+	return 0;
+}
+
+unsigned int get_ring_irq(struct aotg_hcd *acthcd)
+{
+	unsigned int data;
+	unsigned int i;
+	unsigned int pending = 0;
+
+//	printk("%s,INdma(0x%p):0x%x\n", __FUNCTION__,
+//		acthcd->base + HCINxDMAIRQ0, 
+//		readw(acthcd->base + HCINxDMAIRQ0));
+		
+	data = readw(acthcd->base+ HCINxDMAIRQ0);
+	
+	if (data) {
+		for (i = 1; i < 16; i++) {
+			if (data & (0x1 << i)) {
+				pending = i;
+				return pending;
+			}
+		}
+	}
+	
+	data = readw(acthcd->base + HCOUTxBUFEMPTYIRQ0);
+	
+	if (data) {
+		for (i = 1; i < 16; i++) {
+			if (data & (0x1 << i)) {
+				pending = i | AOTG_DMA_OUT_PREFIX;
+				return pending;
+			}
+		}
+	}
+
+	return pending;
+}
+
+void clear_ring_irq(struct aotg_hcd *acthcd, unsigned int irq_mask)
+{
+	int index;
+	u8 is_out = irq_mask & AOTG_DMA_OUT_PREFIX;
+	index = irq_mask & 0xf;
+//	u32 cnt;
+
+	
+	if (is_out) {
+		writew((0x1 << index), (acthcd->base + HCOUTxBUFEMPTYIRQ0));
+	} else {
+		writew((0x1 << index), (acthcd->base + HCINxDMAIRQ0));
+	}
+
+//	printk("%s,(0x%p):0x%x\n", __FUNCTION__,
+//		acthcd->base + HCOUTxBUFEMPTYIRQ0,
+//		readw(acthcd->base + HCOUTxBUFEMPTYIRQ0));
+	
+	return;
+}
+
+int finish_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, struct aotg_td *td)
+{
+	struct urb *urb;
+	struct aotg_trb *trb;
+	int num_trbs;
+	int i, trb_tx_len, length = 0;
+	int status;
+
+	urb = td->urb;
+	trb = td->trb_vaddr;
+	num_trbs = td->num_trbs;
+
+	if (td->cross_ring) {
+		if ((ring->last_trb->hw_token & TRB_OF) != 0)
+			return -1;
+		td->cross_ring = 0;
+		aotg_set_trb_as_ring_linkaddr(ring, ring->first_trb);
+		usb_setbitsl(DMACTRL_DMACS, ring->reg_dmactrl);
+		//aotg_hcd_dump_trb(ring, ring->first_trb);
+		return 1;
+	}
+
+	for (i = 0; i < num_trbs; i++) {
+		if (trb->hw_token & (AOTG_TRB_IOS | AOTG_TRB_IOZ)){
+			trb_tx_len = trb->hw_buf_len - trb->hw_buf_remain;
+			length += trb_tx_len;
+			break;
+		} else if (trb->hw_token & AOTG_TRB_IOC) {
+			length += trb->hw_buf_len;
+		} else {
+//			printk("%s, td still not finish\n", __FUNCTION__);
+			//aotg_hcd_dump_td(ring, td);
+			return -1;
+		}
+		if (trb == ring->last_trb)
+			trb = ring->first_trb;
+		else
+			trb += 1;
+	}
+
+#if 0
+	if (usb_pipetype(urb->pipe) == PIPE_BULK)
+		aotg_hcd_dump_td(ring, td);
+#endif 
+
+	dequeue_td(ring, td, TD_IN_FINISH);
+
+	urb->actual_length = length;
+	status = 0;
+
+
+	if (urb->actual_length > urb->transfer_buffer_length) {
+		ACT_HCD_DBG
+		urb->actual_length = 0;
+		if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+			status = -EREMOTEIO;			
+		else
+			status = 0;
+	}
+	
+	usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
+	spin_unlock(&acthcd->lock);
+	usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status);
+	spin_lock(&acthcd->lock);
+	/* when unlock,maybe list_del(&td->enring_list) in dequeue_td*/
+	if ((urb->ep) && unlikely(!urb->ep->enabled)) {
+		return -1;
+	}
+	
+	return 0;
+}
+
+int intr_finish_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, struct aotg_td *td)
+{
+	int length;
+	int status;
+	struct urb *urb;
+	struct aotg_trb *trb;
+
+	trb = td->trb_vaddr;
+	if (td->urb == NULL) {
+		//printk("%s err, pls fix it!\n", __FUNCTION__);
+		if ((trb->hw_token&TRB_OF) == 0) {
+				aotg_stop_ring(ring);
+		} 
+		return -1;
+	}
+	
+
+	urb = td->urb;
+
+	if (trb->hw_token & (AOTG_TRB_IOS | AOTG_TRB_IOZ)){
+		length = trb->hw_buf_len - trb->hw_buf_remain;
+	} else if (trb->hw_token & AOTG_TRB_IOC) {
+		length = trb->hw_buf_len;
+	} else {
+		return -1;
+	}
+
+	if (!ring->is_out)
+		memcpy(urb->transfer_buffer, td->intr_mem_vaddr, length);
+	dequeue_intr_td(ring, td);
+	
+	urb->actual_length = length;
+	status = 0;
+
+	usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
+	spin_unlock(&acthcd->lock);
+	usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status);
+	spin_lock(&acthcd->lock);
+	
+	return 0;
+}
+
+int isoc_finish_td(struct aotg_hcd *acthcd, struct aotg_ring *ring, struct aotg_td *td)
+{
+	struct urb *urb;
+	struct aotg_trb *trb;
+	int num_trbs;
+	int i, trb_tx_len, length = 0;
+	int status;
+
+//	mb();
+	if (!ring || !td || ((struct list_head *)(&td->enring_list)->next == LIST_POISON1)) {
+		ACT_HCD_ERR
+		return -1;
+	}
+
+	urb = td->urb;
+	if (!urb || !urb->dev)
+		return -1;
+	trb = td->trb_vaddr;
+	num_trbs = td->num_trbs;
+
+	for (i = 0; i < num_trbs; i++) {
+		if (trb->hw_token & (AOTG_TRB_IOS | AOTG_TRB_IOZ)){
+			trb_tx_len = trb->hw_buf_len - trb->hw_buf_remain;
+			urb->iso_frame_desc[i].actual_length = trb_tx_len;
+			urb->iso_frame_desc[i].status = 0;
+			length += trb_tx_len;
+		} else if (trb->hw_token & AOTG_TRB_IOC) {
+			trb_tx_len = trb->hw_buf_len;
+			urb->iso_frame_desc[i].actual_length = trb_tx_len;
+			urb->iso_frame_desc[i].status = 0;
+			length += trb->hw_buf_len;
+		} else {
+			//printk("%s, td still not finish\n", __FUNCTION__);
+			//aotg_hcd_dump_td(ring, td);
+			return -1;
+		}
+		if (trb == ring->last_trb)
+			trb = ring->first_trb;
+		else
+			trb += 1;
+	}
+
+	td->urb = NULL;
+	dequeue_td(ring, td, TD_IN_FINISH);
+
+	urb->actual_length = length;
+	status = 0;
+
+	usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
+	spin_unlock(&acthcd->lock);
+	usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status);
+	spin_lock(&acthcd->lock);
+	
+	return 0;
+}
+
+void handle_ring_dma_tx(struct aotg_hcd *acthcd, unsigned int irq_mask)
+{	
+	int ret;
+	struct aotg_td *td = NULL, *next;	
+	struct aotg_ring *ring;
+	struct aotg_hcep *ep;
+	
+	if (AOTG_IS_DMA_OUT(irq_mask)) {
+		ep = acthcd->outep[AOTG_GET_DMA_NUM(irq_mask)];
+	} else {
+		ep = acthcd->inep[AOTG_GET_DMA_NUM(irq_mask)];
+	}
+	if (ep == NULL) {
+		ACT_HCD_ERR
+		return;
+	}
+	ep->error_count = 0;
+
+	ring = ep->ring;
+	if (!ring) {
+		ACT_HCD_ERR
+		return;
+	}
+
+	if (list_empty(&ep->enring_td_list) || ring_empty(ring))
+		return;
+
+	if (ring->type == PIPE_ISOCHRONOUS) {
+		do {
+			mb();
+			td = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+			if (!td)
+				break;
+			ret = isoc_finish_td(acthcd, ring, td);
+		} while (ret == 0);
+
+		if (!list_empty(&ep->queue_td_list)) {
+			list_for_each_entry_safe(td, next, &ep->queue_td_list, queue_list) {
+				ret = aotg_ring_enqueue_isoc_td(acthcd, ring, td);
+				if (ret)
+					return;
+				list_del(&td->queue_list);
+				list_add_tail(&td->enring_list, &ep->enring_td_list);
+				ring->enring_cnt++;
+			}
+		}
+
+		if (!list_empty(&ep->enring_td_list) && !is_ring_running(ring)) {
+			if (ring->dequeue_trb != ring->first_trb)
+				aotg_reorder_iso_td(acthcd, ring);
+			aotg_start_ring(ring, ring_trb_virt_to_dma(ring, ring->dequeue_trb));
+		}
+		else if (list_empty(&ep->enring_td_list) && is_ring_running(ring)) {
+			aotg_stop_ring(ring);
+		}
+		return;
+	} else if (ring->type == PIPE_INTERRUPT) {
+		if (!ring->intr_started)
+			return;
+		do {
+			mb();
+			td = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+			if (!td)
+				break;
+			ret = intr_finish_td(acthcd, ring, td);
+		} while (ret == 0);
+
+		if (!is_ring_running(ring)) {
+			pr_debug("%s, intr stop!\n", __func__);
+		}
+		return;
+	}
+
+	do {
+		mb();
+		td = list_first_entry_or_null(&ep->enring_td_list, struct aotg_td, enring_list);
+		if (!td)
+			break;
+		ret = finish_td(acthcd, ring, td);
+	} while (ret == 0);
+	
+	if (ret == 1)
+		return;
+
+	if (!list_empty(&ep->queue_td_list)) {
+		list_for_each_entry_safe(td, next, &ep->queue_td_list, queue_list) {
+			ret = aotg_ring_enqueue_td(acthcd, ring, td);
+			if (ret) {
+				return;
+			}
+			list_del(&td->queue_list);
+			list_add_tail(&td->enring_list, &ep->enring_td_list);
+			ring->enring_cnt++;
+		}
+	}
+
+	if (!list_empty(&ep->enring_td_list) && !is_ring_running(ring))
+		aotg_start_ring(ring, ring_trb_virt_to_dma(ring, ring->dequeue_trb));
+	else if (list_empty(&ep->enring_td_list) && is_ring_running(ring))
+		aotg_stop_ring(ring);
+}
+
+void aotg_ring_irq_handler(struct aotg_hcd *acthcd)
+{
+	unsigned int irq_mask;
+	unsigned long flags;
+
+	spin_lock_irqsave(&acthcd->lock, flags);
+	acthcd->check_trb_mutex = 1;
+
+	do {
+		irq_mask = get_ring_irq(acthcd);
+		if (irq_mask == 0) {
+			acthcd->check_trb_mutex = 0;
+			spin_unlock_irqrestore(&acthcd->lock, flags);
+			return;
+		}
+		clear_ring_irq(acthcd, irq_mask);
+
+		handle_ring_dma_tx(acthcd, irq_mask);
+	} while (irq_mask);
+	acthcd->check_trb_mutex = 0;
+	spin_unlock_irqrestore(&acthcd->lock, flags);
+	return;
+}
+
+
+
diff --git a/drivers/usb/host/aotg_ring.h b/drivers/usb/host/aotg_ring.h
new file mode 100644
index 0000000..fe69508
--- /dev/null
+++ b/drivers/usb/host/aotg_ring.h
@@ -0,0 +1,48 @@
+#ifndef  __LINUX_USB_AOTG_RING_H__ 
+#define  __LINUX_USB_AOTG_RING_H__ 
+
+/* about dma_no: if (dma_no & 0x10) == 0x10, it's hcout, otherwise it's hcin. */
+
+
+void aotg_hcd_dump_trb(struct aotg_trb *trb);
+void aotg_hcd_dump_td(struct aotg_td *td);
+void enable_overflow_irq(struct aotg_hcd *acthcd, struct aotg_hcep *ep);
+void disable_overflow_irq(struct aotg_hcd *acthcd, struct aotg_hcep *ep);
+void clear_overflow_irq(struct aotg_hcd *acthcd, struct aotg_hcep *ep);
+struct aotg_td *aotg_alloc_td(gfp_t mem_flags);
+void aotg_release_td(struct aotg_td *td);
+int is_ring_running(struct aotg_ring *ring);
+void start_ring(struct aotg_ring *ring);
+void stop_ring(struct aotg_ring *ring);
+struct aotg_ring *aotg_alloc_ring(struct aotg_hcd *acthcd,
+				struct aotg_hcep *ep, unsigned int num_trbs, 
+				gfp_t mem_flags);
+void aotg_free_ring(struct aotg_hcd *acthcd, struct aotg_ring *ring);
+dma_addr_t ring_trb_virt_to_dma(struct aotg_ring *ring, 							struct aotg_trb *trb_vaddr);
+int ring_empty(struct aotg_ring *ring);
+inline int is_room_on_ring(struct aotg_ring *ring, unsigned int num_trbs);
+inline unsigned int	count_urb_need_trbs(struct urb *urb);
+void aotg_fill_trb(struct aotg_trb *trb,
+					u32 dma_addr, u32 len, u32 token);
+int aotg_sg_map_trb(struct aotg_trb *trb, 
+						struct scatterlist *sg, int len, u32 token);
+void inc_enqueue_safe(struct aotg_ring *ring);
+void enqueue_trb(struct aotg_ring *ring, u32 buf_ptr, u32 buf_len,
+				u32 token); 
+int ring_enqueue_sg_td(struct aotg_hcd *acthcd,
+				struct aotg_ring *ring, struct aotg_td *td); 
+int aotg_ring_enqueue_td(struct aotg_hcd *acthcd, 
+				struct aotg_ring *ring, struct aotg_td *td); 
+void inc_dequeue_safe(struct aotg_ring *ring);
+void aotg_ring_dequeue_td(struct aotg_ring *ring, struct aotg_td *td);
+unsigned int get_ring_irq(struct aotg_hcd *acthcd);
+void clear_ring_irq(struct aotg_hcd *acthcd, unsigned int irq_mask);
+int finish_td(struct aotg_ring *ring, struct aotg_td *td);
+void handle_ring_dma_tx(struct aotg_hcd *acthcd, unsigned int irq_mask);
+void aotg_ring_irq_handler(struct aotg_hcd *acthcd);
+ 
+#endif
+
+
+
+
diff --git a/drivers/usb/host/uhost_hotplug_handle.c b/drivers/usb/host/uhost_hotplug_handle.c
new file mode 100644
index 0000000..f135771
--- /dev/null
+++ b/drivers/usb/host/uhost_hotplug_handle.c
@@ -0,0 +1,34 @@
+#define SUPPORT_NOT_RMMOD_USBDRV 1
+#if SUPPORT_NOT_RMMOD_USBDRV
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+enum plugstate{
+	PLUGSTATE_A_OUT=0,
+  PLUGSTATE_B_OUT,
+	PLUGSTATE_A_IN,
+	PLUGSTATE_B_IN,
+	PLUGSTATE_A_SUSPEND,
+	PLUGSTATE_A_RESUME,	
+};
+
+extern int xhci_resume_host(void);
+extern int xhci_suspend_host(void);
+
+ int xhci_set_plugstate(int state)
+{
+		if((state==PLUGSTATE_A_SUSPEND)){	
+			    printk("\n----xhci_set_plugstate--HOST_SUSPEND--\n");				  		
+				xhci_suspend_host();
+		}
+		else if((state==PLUGSTATE_A_RESUME)){  
+			    printk("\n----xhci_set_plugstate--HOST_RESUME--\n");				  		
+				xhci_resume_host();
+		}
+		return 0;
+}
+EXPORT_SYMBOL_GPL(xhci_set_plugstate);
+
+#endif
\ No newline at end of file
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
old mode 100644
new mode 100755
index 896b928..4eaf1e6
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -31,12 +31,22 @@
 
 #include "xhci.h"
 #include "xhci-trace.h"
+#define XHCI_SUPPORT_SUPERSPEED	
+#ifdef XHCI_SUPPORT_SUPERSPEED	
+#include "xhci_ss_retry_mode.c"
+#include "xhci_ss_phy_setting.c"
+#endif
 
 #define DRIVER_AUTHOR "Sarah Sharp"
 #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
 
 #define	PORT_WAKE_BITS	(PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
 
+struct xhci_hcd *xhci_host;
+extern void dwc3_phy_init(u8 mode, unsigned char port_num);
+extern void disable_bias(void);
+extern void enable_bias(void);
+
 /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
 static int link_quirk;
 module_param(link_quirk, int, S_IRUGO | S_IWUSR);
@@ -129,6 +139,12 @@ static int xhci_start(struct xhci_hcd *xhci)
 	u32 temp;
 	int ret;
 
+#ifdef XHCI_SUPPORT_SUPERSPEED      
+	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+        
+	ss_lfps_init(hcd->regs) ;
+#endif
+ 
 	temp = readl(&xhci->op_regs->command);
 	temp |= (CMD_RUN);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Turn on HC, cmd = 0x%x.",
@@ -149,6 +165,29 @@ static int xhci_start(struct xhci_hcd *xhci)
 		/* clear state flags. Including dying, halted or removing */
 		xhci->xhc_state = 0;
 
+#ifdef XHCI_SUPPORT_SUPERSPEED    
+	printk("\n#xhci_start#\n");
+#ifdef XHCI_SS_SUPPORT_RETRY     
+	int val,retry_cnt = 0;
+	ReRxDetectLoop_notResetXhci:  
+	do{
+		ss_retry_mode(hcd->regs);
+		printk("ss retry %d times\n",retry_cnt++);
+        	msleep(10);
+		if(ss_detect_ltssm_change(hcd->regs)==0)
+		{				
+			if((retry_cnt >10))
+				break;
+			goto ReRxDetectLoop_notResetXhci; 
+		}
+		val = readl(hcd->regs+XHCI_PORT2_STATUS);
+	}
+	while(((val & PORT_CONNECT) ==0)&&(retry_cnt <10) );// try 10 times ,then try hs
+#else
+	ss_retry_mode(hcd->regs);
+#endif
+#endif
+
 	return ret;
 }
 
@@ -165,6 +204,12 @@ int xhci_reset(struct xhci_hcd *xhci)
 	u32 state;
 	int ret, i;
 
+	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+    
+#ifndef XHCI_SUPPORT_SUPERSPEED       
+	enable_bias();
+#endif  
+
 	state = readl(&xhci->op_regs->status);
 	if ((state & STS_HALT) == 0) {
 		xhci_warn(xhci, "Host controller not halted, aborting reset.\n");
@@ -206,6 +251,15 @@ int xhci_reset(struct xhci_hcd *xhci)
 		xhci->bus_state[i].resuming_ports = 0;
 	}
 
+	dwc3_phy_init(1,0);
+    
+#ifdef XHCI_SUPPORT_SUPERSPEED   
+	ss_phy_init(hcd->regs,1);
+	ss_retry_mode_init(hcd->regs);
+#else
+	disable_bias();
+#endif 
+
 	return ret;
 }
 
@@ -578,6 +632,8 @@ static int xhci_run_finished(struct xhci_hcd *xhci)
 	if (xhci->quirks & XHCI_NEC_HOST)
 		xhci_ring_cmd_db(xhci);
 
+	xhci_host = xhci;
+
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"Finished xhci_run for USB3 roothub");
 	return 0;
@@ -906,6 +962,15 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
  * This is called when the machine transition into S3/S4 mode.
  *
  */
+int xhci_suspend_host(void)
+{
+	struct usb_hcd *hcd = xhci_to_hcd(xhci_host);
+
+	xhci_suspend(xhci_host, device_may_wakeup(hcd->self.controller));
+
+	return 0;	
+}
+
 int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
 {
 	int			rc = 0;
@@ -991,6 +1056,12 @@ EXPORT_SYMBOL_GPL(xhci_suspend);
  * This is called when the machine transition from S3/S4 mode.
  *
  */
+int xhci_resume_host(void)
+{
+	xhci_resume(xhci_host, 0);
+	return 0;
+}
+
 int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
 	u32			command, temp = 0, status;
diff --git a/drivers/usb/host/xhci_ss_phy_setting.c b/drivers/usb/host/xhci_ss_phy_setting.c
new file mode 100644
index 0000000..893d6ab
--- /dev/null
+++ b/drivers/usb/host/xhci_ss_phy_setting.c
@@ -0,0 +1,131 @@
+#ifdef XHCI_SUPPORT_SUPERSPEED       
+
+static void set_reg32_val(void __iomem *base , unsigned int mask, unsigned int val, unsigned int reg)
+{
+	unsigned int Wtmp;
+
+	Wtmp =readl(base +  reg);
+	Wtmp &= ~(mask);
+	val &= mask;
+	Wtmp |= val ;    
+	writel(Wtmp,base +  reg);
+}
+
+static void ss_phy_rx_init(void __iomem *base)
+{
+
+	//modified by lchen
+	set_reg32_val(base , 0x1f<<1, 0x15<<1, USB3_ANA03); 	//for lowest OOBS_sensitivity
+	set_reg32_val(base ,0x3<<14, 0x2<<14, USB3_ANA0B); 	//for OOBS CM, default 10
+	set_reg32_val(base ,0x3<<12, 0x2<<12, USB3_ANA0B); 	//for OOBS DM, default 10
+	writel( 0x9555, base +  USB3_ANA04);	//for CMU_LDO=2.1V	
+	writel(0x2d91,base + USB3_ANA08);	//for proper DC gain
+	
+	set_reg32_val(base ,0x1<<6, 0x0<<6, USB3_ANA09); 	//for RXIDLE=LFPS_DET & NSQ(1) or NSQ(0)
+	set_reg32_val(base , 0x7<<12, 0x3<<12, USB3_ANA09); 	//for IB_TX and IB_OOBS	
+	writel(0xFF68 ,base + USB3_ANA0D);	//for CDR_PI and RX_Z0	
+	writel(0x2020,base + USB3_ANA0E);	//for TX_CM mode
+	writel(0xFF0C, base + USB3_REV2);		//for CDR and PI in 0x1B---[0xFF08--BAD]
+	set_reg32_val(base , 0x7<<2, 0x7<<2, USB3_REV3); 	//for CP0 selected	
+
+	//set_reg32_val(base , 0x1<<0, 0x0<<0, USB3_FLD0); 	//for disable BER checker	
+
+	writel(0xD4FF,base + USB3_PAGE1_REG00);		//for 0x20 TX_DRV
+	writel(0xAAFF,base + USB3_PAGE1_REG01);		// TX_DRV
+	writel(0x0051,base + USB3_PAGE1_REG02);		// TX_DRV   and BER ckecker sel
+	writel(0xDB60,base + USB3_PAGE1_REG03);		// TX_DRV
+
+	//for force offset value
+	set_reg32_val(base , 0xf<<5, 0x9<<5, USB3_ANA0B); 			
+	//set_reg32_val(base , 0x1<<13, 0x0<<13, USB3_ANA0D); //manual set when 0
+	
+	//for CDR loop setup earlier
+	set_reg32_val(base ,0x1<<1, 0x1<<1, USB3_ANA0B); 	//for PIEN select change
+	set_reg32_val(base ,0x1<<15, 0x0<<15, USB3_ANA0C); 	//for POW_CLK(PSAVE) select change
+	set_reg32_val(base ,0x1<<3, 0x0<<3, USB3_ANA00); 	//for cdr RESET select change(POWER DISPPU)
+	set_reg32_val(base ,0x1<<10, 0x0<<10, USB3_ANA0D); 	//for CDR digitalLFP ENABLE select change	
+
+	//for manual mode CDR_ST<31:0>
+	set_reg32_val(base ,0x1<<15, 0x1<<15, USB3_ANA02); 	//for enable manual set ST value
+	set_reg32_val(base ,0xffff<<0, 0x0<<0, USB3_PAGE1_REG0C); 	//for ST[31:16]
+	set_reg32_val(base ,0xffff<<0, 0xff<<0, USB3_PAGE1_REG0D); 	//for ST[15:0]
+	
+	//for PI bias	
+	set_reg32_val(base ,0x3<<3, 0x1<<3, USB3_REV2); 	//for PI bias[3:2] default=1
+	set_reg32_val(base ,0x3<<11, 0x2<<11, USB3_ANA0D); 	//for PI bias[1:0] default=2	
+
+	//for force EQ value      
+	//setReg32_val(0x1<<14, 0x0<<14, USB3_PAGE1_REG00);	//for manual mode when REG_CDR_SEL=0			
+	set_reg32_val(base ,0x1<<5, 0x1<<5, USB3_ANA0A);	       //for manual set when REG_RX_EQ_SELREG=1	
+	set_reg32_val(base ,0x1f<<11, 0x7<<11, USB3_REV0);	       //for REG_FILTER_OUT=from 11100 to 10000	
+	
+	//APHY Dbg Switch 
+	set_reg32_val(base ,  1<<0, 1<<0, USB3_ANA0D); //for TX_TEST_EN=1	
+	set_reg32_val(base ,1<<6, 1<<6, USB3_ANA0D);	//for RX_TEST_EN=1	
+	set_reg32_val(base , 1<<9, 1<<9, USB3_ANA02); 	//for CDR_TEST_EN=1	
+	set_reg32_val(base , 0x7<<10, 0x2<<10, USB3_ANA02); 	//for CDR_TESTOUT_SEL=CLKDEBUG	
+}
+
+static void ss_phy_analog_setting(void __iomem *base)
+{
+	writel(0x8000,base + USB3_ANA0F);
+	writel(0x6046,base + USB3_ANA02);
+	writel(0x2020,base + USB3_ANA0E);
+
+	writel(0x0,base + USB3_REV1);
+	writel(0x0013,base + USB3_PAGE1_REG02);
+	writel(0x0004,base + USB3_PAGE1_REG06);
+	writel(0x22ed,base + USB3_PAGE1_REG07);
+	writel(0xf802,base + USB3_PAGE1_REG08);
+	writel(0x3080,base + USB3_PAGE1_REG09);
+	writel(0x2030,base + USB3_PAGE1_REG0B);
+
+	ss_phy_rx_init(base);
+    
+	set_reg32_val(base , ((1<<5)|(1<<4)),((1<<5)|(0<<4)),USB3_ANA0E);//bit4: [0=cmfb mode=usingRxDetect]  [1=opab  mode=Nomal Using]
+	set_reg32_val(base , (3<<12),(2<<12),USB3_ANA0E);//Tx_SCE_VCM
+	set_reg32_val(base , (3<<2),(0<<2),USB3_ANA0C);//RxSel---time
+	set_reg32_val(base , (1<<15),(0<<15),USB3_FLD0);
+
+	set_reg32_val(base , (3<<0),(2<<0),USB3_ANA08); //Rx DC gain
+	set_reg32_val(base ,(3<<1),(3<<1),USB3_PAGE1_REG06); // DC gain--DB
+	set_reg32_val(base ,((7<<0)|(7<<3)|(7<<6)),((1<<0)|(1<<3)|(4<<6)),USB3_ANA01);
+}
+/*
+* host_dev: 0: device; 1: host
+*/
+void ss_phy_init(void __iomem *base,int host_dev)
+{	     
+	ss_phy_analog_setting(base);
+
+	set_reg32_val(base ,((1<<5)|(1<<3)),((1<<5)|(0<<3)), USB3_PAGE1_REG0B);//must bit3=0---20140925
+	set_reg32_val(base ,(1<<7),(0<<7), USB3_PAGE1_REG0A);//must bit7=0---20140925
+	set_reg32_val(base ,(0xF<<2),(0x7<<2), USB3_ANA0D);
+	//set_reg32_val(base ,(1<<3),(0<<3), USB3_PAGE1_REG0B);//
+	//set_reg32_val(base ,((1<<8)|(1<<10)),((0<<8)|(0<<10)), USB3_FLD1);//	
+	//set_reg32_val(base ,(1<<7),(0<<7), USB3_PAGE1_REG0A);//
+	set_reg32_val(base ,(1<<0),(0x1<<0), USB3_FLD0); //Biterr Checker Function Disable---20141127
+	writel(0,base + USB3_IER);
+	set_reg32_val(base ,(1<<11),(1<<11), USB3_REV3);//rcv clock sample	
+
+	set_reg32_val(base ,(0xf<<12),(0x6<<12), USB3_ANA02); //care---or will go to HS
+	set_reg32_val(base ,(0xf<<0),(0xd<<0), USB3_ANA03); //care---or will sometime goto HS
+	set_reg32_val(base ,(0xff<<8),(0xfc<<8), USB3_IER); //care
+	if(host_dev==1){
+		set_reg32_val(base ,(0xf<<0),(0x8<<0), USB3_PAGE1_REG0B);//care
+		set_reg32_val(base , (3<<0),(3<<0),USB3_ANA08); //Rx DC gain
+	}
+	else{		
+
+		set_reg32_val(base , (1<<22) , (0<<22), BACKDOOR); //LUP timing select--20140624
+		set_reg32_val(base ,(1<<9)|(1<<8) , (1<<9)|(1<<8), BACKDOOR); //Mac SampleEdge select--20140624			
+		set_reg32_val(base ,((1<<3)|(0x3f<<4)), ((0<<3)|(36<<4)), USB3_DMR);//enableDebug Out		
+		set_reg32_val(base , (1<<9)  , (1<<9) , BACKDOOR); //Mac SampleEdge select
+	
+	}
+	set_reg32_val(base ,(1<<14),(1<<14), GUCTL);//fix asix usbnet dongle retry hangup
+	set_reg32_val(base ,(1<<17),(1<<17), GUCTL);//fix some udisk control transfer too slow,set config fail
+	writel(0x2408,base + GUSB2CFG0);
+} 
+EXPORT_SYMBOL_GPL(ss_phy_init);
+#endif
diff --git a/drivers/usb/host/xhci_ss_retry_mode.c b/drivers/usb/host/xhci_ss_retry_mode.c
new file mode 100644
index 0000000..42ff795
--- /dev/null
+++ b/drivers/usb/host/xhci_ss_retry_mode.c
@@ -0,0 +1,224 @@
+#ifdef XHCI_SUPPORT_SUPERSPEED       
+
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include "xhci_usb3_regs.h"
+
+extern int usb_set_vbus_power(int value);
+#define  LfpsSrc_Mode_LPFS_DET	(1)
+#define  LfpsSrc_Mode_NSQ		(2)
+#define  LfpsSrc_Mode_BOTH		(3)
+
+//unsigned int capltssm[64/4];  //char[64]
+//unsigned int capltssm_curr_idx;
+static int lfps_src_mode = LfpsSrc_Mode_LPFS_DET; 
+unsigned int ltssm_old,ltssm_curr;
+static void set_reg32_val(void __iomem *base , unsigned int mask, unsigned int val, unsigned int reg);
+void  ss_mac_sample_edge_init(void __iomem *base );
+#ifdef XHCI_SS_SUPPORT_RETRY   
+static int ss_detect_ltssm_change(void __iomem *base)
+{
+	volatile unsigned int Wtmp ;
+	//int ret=1;
+	//volatile unsigned int  tmp_ts1;
+	//unsigned int  cap;
+	//unsigned char * pU8= (unsigned char *)capltssm;
+	int cnt = 0xffff;
+    
+    	for(cnt = 0;cnt <100;cnt++){
+            	mdelay(1);    
+		Wtmp =readl(GDBGLTSSM+base);
+		if((Wtmp&(0xf<<22))==0) {
+			// connected
+			printk(KERN_ERR"\n== in U0 ,don't need retry ==\n");
+			return 1;
+		}  		    
+	}
+	printk(KERN_ERR"\n----wait U0 fail!!---\n");    
+    	return 0;
+        
+#if 0    
+	Wtmp =readl(USB3_GDBGLTSSM+base);
+	ltssm_curr =  Wtmp & ((0xf<<22)|(0xf<<18));
+	if(ltssm_curr != ltssm_old )
+	{
+		//pU8[capltssm_curr_idx++] = (ltssm_curr>>18);
+		//capltssm_curr_idx &= (64-1);
+		printk("\n-----detectLtssChange-----USB3_GDBGLTSSM=0x%x----Ltssm_curr=0x%x--Ltssm_old=0x%x--\n",\
+            		Wtmp,ltssm_curr,ltssm_old);
+
+		if((Wtmp &(0xf<<22))==(0x7<<22))
+		{
+			while(1)
+			{
+				tmp_ts1 = readl(USB3_GDBGLTSSM+base) & ((0xf<<22)|(0xf<<18));
+				Wtmp =tmp_ts1 & (0xf<<22);
+				if(Wtmp==0){
+					printk("\n=============in U0============\n");
+					break;  //if=U0
+				}
+				else if(Wtmp==(0xa<<22))  //if=Complaint
+				{
+					Wtmp =Wtmp>>18;  //add for easy to see Ltssm State
+					ret =0; 
+					return ret;
+				}else if(Wtmp==(0x5<<22)) //if =RxDetect again
+				{
+					printk("\n===========RxDetect again========\n\n");
+					while(1)
+					{
+						Wtmp = readl(USB3_GDBGLTSSM+base) & (0xf<<22);
+						Wtmp = Wtmp>>22;
+						if(Wtmp==(0xa<<0))   {
+							ret =0; 
+							return ret;
+						}  
+						else if(Wtmp==0 )  
+						break;
+                        			cnt--;
+                                    	if(cnt <= 0)
+                                            return 0;
+					}
+					break;
+				}
+				else if(Wtmp==(0x7<<22))
+					cap = tmp_ts1>>18;
+			}
+		}
+	}
+	ltssm_old= ltssm_curr;	
+	ret = 1;// connect
+	return ret;
+#endif    
+} 
+#endif
+static void ss_try_next_mode(void __iomem *base)
+{  
+    	printk(" ss_try_next_mode:lfps_src_mode=%d\n",lfps_src_mode );
+	switch(lfps_src_mode)
+	{
+		case LfpsSrc_Mode_LPFS_DET :
+		{
+			set_reg32_val(base ,  (1<<9), (0<<9), GUSB3PIPECTL); //  for Test=LFPS Filter 
+			set_reg32_val(base , ((1<<8)|(1<<15)),((0<<8)|(0<<15)), USB3_FLD0); 
+			set_reg32_val(base , (1<<3),(0<<3), USB3_PAGE1_REG0B);  //active--will remove false Lfps In JiaJun--20150330
+			break;
+		}
+		
+		case LfpsSrc_Mode_NSQ :
+		{
+			set_reg32_val(base , (1<<9), (0<<9), GUSB3PIPECTL); //  for Test=LFPS Filter 
+			set_reg32_val(base , ((1<<8)|(1<<15)),((0<<8)|(0<<15)), USB3_FLD0); 
+			set_reg32_val(base , ((1<<3)|(1<<5)),((1<<3)|(1<<5)), USB3_PAGE1_REG0B);  //active--will remove false Lfps In JiaJun--20150330
+			break;
+		}	
+		
+		case LfpsSrc_Mode_BOTH :
+		{  
+			set_reg32_val(base , (1<<9), (0<<9), GUSB3PIPECTL); //  for Test=LFPS Filter 
+			set_reg32_val(base , ((1<<8)|(1<<15)),((0<<8)|(0<<15)), USB3_FLD0); 
+			set_reg32_val(base , ((1<<3)|(1<<5)),((1<<3)|(1<<5)), USB3_PAGE1_REG0B);  //active--will remove false Lfps In JiaJun--20150330
+			set_reg32_val(base , (1<<6),(1<<6), USB3_ANA09); 
+			break;
+		}
+		
+		default:
+		{
+			break;
+		}		
+	}
+	//if(++lfps_src_mode >LfpsSrc_Mode_BOTH)
+	//	lfps_src_mode = LfpsSrc_Mode_LPFS_DET;
+}
+
+void ss_retry_phy_softrest(void __iomem *base)
+{
+	set_reg32_val(base ,  (1<<31),(1<<31), GUSB3PIPECTL);  //PHY softRest
+	mdelay(10);
+	set_reg32_val(base ,  (1<<31),(0<<31), GUSB3PIPECTL);  //PHY softRest
+}
+
+void ss_retry_mode(void __iomem *base)
+{
+	unsigned int val;
+    
+	writel((1<<14),USB3_ANA0F+base);
+	
+	usb_set_vbus_power(0);
+    
+	ss_retry_phy_softrest(base);
+	mdelay(5);
+    	ss_mac_sample_edge_init(base ); 
+	ss_try_next_mode(base);	
+	mdelay(5);
+    
+	usb_set_vbus_power(1);
+    
+	mdelay(1);
+    
+    	val = 0x200;
+	writel(val,base+XHCI_PORT2_STATUS);	
+	set_reg32_val(base ,0xff, 2, GBDGFIFOSPACE); //select port2
+	
+}
+
+void  ss_mac_sample_edge_init(void __iomem *base )
+{
+	set_reg32_val(base , (1<<22) , (0<<22), BACKDOOR); //LUP timing select--20140624
+	set_reg32_val(base ,(1<<9)|(1<<8) , (1<<9)|(0<<8), BACKDOOR); //Mac SampleEdge select--20140624	
+	set_reg32_val(base , (1<<9)  , (1<<9) , BACKDOOR); //Mac SampleEdge select
+}
+
+void ss_lfps_init(void __iomem *base)
+{
+	set_reg32_val(base ,  (1<<8), (0<<8), USB3_GCTL); //Not Infinit
+	set_reg32_val(base , (1<<12), (1<<12), GUSB3PIPECTL); //  for Test=LFPS P0 Align (LFPSP0Algn)
+	set_reg32_val(base ,  (1<<9), (0<<9), GUSB3PIPECTL); //  for Test=LFPS Filter 
+	set_reg32_val(base , (3<<12), (1<<12), USB3_GCTL);
+} 
+#if 0
+void ss_detect_ltssm_init(void __iomem *base)
+{												
+	set_reg32_val(base ,0xff, 2, USB3_GBDGFIFOSPACE); //select port2
+	ltssm_old =readl(USB3_GDBGLTSSM+base) & ((0xf<<22)|(0xf<<18)) ;
+	ltssm_curr = ltssm_old;
+	capltssm_curr_idx =0;
+
+	unsigned char * pU8= (unsigned char *)capltssm;
+	pU8[capltssm_curr_idx++] = (ltssm_curr>>18);
+}
+#endif
+void ss_retry_mode_init(void __iomem *base)
+{
+#if 0
+	int i;   
+        
+    	void __iomem *cmu_base = (void __iomem *)IO_ADDRESS(0xB0168000);
+    	set_reg32_val(cmu_base ,((1<<7)|(1<<6)),((1<<7)|(1<<6)), USB3_ECS);//softvbus =1
+	set_reg32_val(cmu_base ,((1<<31)|(7<<28)),((1<<31)|(4<<28)), USB3_ECS); //USB3 USB2PLL LDO Enable	
+#endif	
+
+	ss_mac_sample_edge_init(base ); 
+
+#if 0      
+    	for (i=0;i<1000;i++);	
+   		ss_detect_ltssm_init(base);   
+     
+    	writel(0x00001448 ,base + USB3_GUSB2CFG0);
+    	set_reg32_val(base , (3<<4), (0<<4), USB3_GCTL);  //clean the scale down
+#endif          
+	set_reg32_val(base , (0xff<<0), (0x6<<0), GSBUSCFG0);//enable burst 8 and burst 4
+	set_reg32_val(base , (0xf<<8), (0x7<<8), GSBUSCFG1); //AXI busrt requst limit is 3  
+	
+  	/*set_reg32_val(base , (0x1<<29), (1<<29), USB3_GTXTHRCFG);
+      set_reg32_val(base , (0xf<<24), (0xf<<24), USB3_GTXTHRCFG);
+      set_reg32_val(base , (0xf<<16), (0xf<<16), USB3_GTXTHRCFG);
+      
+      set_reg32_val(base , (0x1<<29), (1<<29), USB3_GRXTHRCFG);
+      set_reg32_val(base , (0xf<<24), (0x3<<24), USB3_GRXTHRCFG);
+      set_reg32_val(base , (0xf<<19), (0x3<<19), USB3_GRXTHRCFG);*/
+      
+}
+#endif
diff --git a/drivers/usb/host/xhci_usb3_regs.h b/drivers/usb/host/xhci_usb3_regs.h
new file mode 100644
index 0000000..59ff164
--- /dev/null
+++ b/drivers/usb/host/xhci_usb3_regs.h
@@ -0,0 +1,79 @@
+#ifdef XHCI_SUPPORT_SUPERSPEED       
+
+#ifndef  __USB3_REGS_H__
+#define  __USB3_REGS_H__
+
+//--------------USB3_Register-------------------------------------------//
+//--------------Register Address---------------------------------------//
+#define USB3_ANA00 (0+0xCD00)
+#define USB3_ANA01 (0+0xCD04)
+#define USB3_ANA02 (0+0xCD08)
+#define USB3_ANA03 (0+0xCD0C)
+#define USB3_ANA04 (0+0xCD10)
+
+#define USB3_ANA05 (0+0xCD14)
+#define USB3_ANA06 (0+0xCD18)
+#define USB3_ANA07 (0+0xCD1C)
+#define USB3_ANA08 (0+0xCD20)
+#define USB3_ANA09 (0+0xCD24)
+#define USB3_ANA0A (0+0xCD28)
+#define USB3_ANA0B (0+0xCD2C)
+#define USB3_ANA0C (0+0xCD30)
+#define USB3_ANA0D (0+0xCD34)
+#define USB3_ANA0E (0+0xCD38)
+#define USB3_ANA0F (0+0xCD3C)
+#define USB3_DMR (0+0xCD40)
+#define USB3_BACR (0+0xCD44)
+#define USB3_IER (0+0xCD48)
+#define USB3_BCSR (0+0xCD4C)
+#define USB3_BPNR2 (0+0xCD54)
+#define USB3_BRNR2 (0+0xCD5C)
+#define USB3_BENR (0+0xCD60)
+#define USB3_REV0 (0+0xCD64)
+#define USB3_REV1 (0+0xCD68)
+#define USB3_REV2 (0+0xCD6C)
+#define USB3_REV3 (0+0xCD70)
+#define USB3_FLD0 (0+0xCD74)
+#define USB3_FLD1 (0+0xCD78)
+#define USB3_ANA1F (0+0xCD7C)
+#define USB3_PAGE1_REG00 (0+0xCD80)
+#define USB3_PAGE1_REG01 (0+0xCD84)
+#define USB3_PAGE1_REG02 (0+0xCD88)
+#define USB3_PAGE1_REG03 (0+0xCD8C)
+#define USB3_PAGE1_REG04 (0+0xCD90)
+#define USB3_PAGE1_REG05 (0+0xCD94)
+#define USB3_PAGE1_REG06 (0+0xCD98)
+#define USB3_PAGE1_REG07 (0+0xCD9C)
+#define USB3_PAGE1_REG08 (0+0xCDA0)
+#define USB3_PAGE1_REG09 (0+0xCDA4)
+#define USB3_PAGE1_REG0A (0+0xCDA8)
+#define USB3_PAGE1_REG0B (0+0xCDAC)
+#define USB3_PAGE1_REG0C (0+0xCDB0)
+#define USB3_PAGE1_REG0D (0+0xCDB4)
+#define USB3_PAGE1_REG0E (0+0xCDB8)
+#define USB3_PAGE1_REG0F (0+0xCDBC)
+#define USB3_PAGE1_REG10 (0+0xCDC0)
+#define USB2_P0_VDCTRL (0+0xCE00)
+#define BACKDOOR (0+0xCE04)
+#define USB3_EXT_CONTROL (0+0xCE08)
+#define USB2_P1_VDCTRL (0+0xCE10) 
+
+#define     GUSB3PIPECTL                        (0+0xC2C0)
+#define     USB3_GCTL                                       (0+0xC110)
+#define     GUCTL                                       (0+0xC12C)
+#define     GBDGFIFOSPACE                      (0+0xC160)
+#define     GDBGLTSSM                             (0+0xC164)
+#define     XHCI_PORT2_STATUS 				(0x0430+0)
+#define     GUSB2CFG0                       		(0+0xC200)
+#define     GSBUSCFG0                       		(0+0xC100)
+#define     GSBUSCFG1                    		(0+0xC104)
+#define     GTXTHRCFG                       	(0+0xC108)
+#define     GRXTHRCFG                    		(0+0xC10C)
+#define     USB3_ECS                          			(0+0x0080)
+
+
+#define USB3_ACTIONS_START        (0xcd00)
+#define USB3_ACTIONS_END          (0xcd58)
+
+#endif
+#endif
diff --git a/drivers/usb/monitor/Kconfig b/drivers/usb/monitor/Kconfig
new file mode 100644
index 0000000..e58bcd4
--- /dev/null
+++ b/drivers/usb/monitor/Kconfig
@@ -0,0 +1,23 @@
+#
+# USB Monitor configuration
+#
+
+config USB_ACTIONS_MON
+	tristate "USB Actions Monitor"
+	depends on ARCH_OWL
+	help
+	  If you select this option, a component which captures the USB traffic
+	  between peripheral-specific drivers and HC drivers will be built.
+	  For more information, see <file:Documentation/usb/usbmon.txt>.
+
+	  If unsure, say Y, if allowed, otherwise M.
+
+config USB_PLATFORM_LINUX
+	tristate "USB Monitor For Linux"
+	depends on ARCH_OWL && USB_ACTIONS_MON
+	help
+	  If you select this option usb monitor just detect usb plug in/out ,sent uevent & open
+	  or close usb controller.
+	  if not , usb monitor will support android system by sent uevent to vold;
+
+	  If unsure, say Y, if allowed, otherwise M.	  
diff --git a/drivers/usb/monitor/Makefile b/drivers/usb/monitor/Makefile
new file mode 100644
index 0000000..4ccdbc4
--- /dev/null
+++ b/drivers/usb/monitor/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for USB monitor
+#
+
+monitor-y := umonitor_core.o umonitor_hal.o umonitor_api.o
+
+obj-$(CONFIG_USB_ACTIONS_MON)		+= monitor.o
+
+
+
diff --git a/drivers/usb/monitor/aotg_regs.h b/drivers/usb/monitor/aotg_regs.h
new file mode 100644
index 0000000..22f018f
--- /dev/null
+++ b/drivers/usb/monitor/aotg_regs.h
@@ -0,0 +1,162 @@
+/*
+ * for Actions AOTG 
+ *
+ */
+
+#ifndef  __AOTG_REGS_H__
+#define  __AOTG_REGS_H__
+
+
+#define USB3_REGISTER_BASE          0xB0400000
+
+#define DWC3_DCFG                   0xc700
+
+
+#define DWC3_ACTIONS_REGS_START     (0xcd00)
+#define DWC3_ACTIONS_REGS_END       (0xcd54)
+
+
+
+
+
+#define DWC3_CDR_KIKD          (0xcd00)
+#define DWC3_CDR_KP1           (0xcd04)
+#define DWC3_TIMER_INIT        (0xcd08)
+#define DWC3_CDR_CONTROL       (0xcd0c)
+#define DWC3_RX_OFFSET_PS      (0xcd10)
+#define DWC3_EQ_CONTROL        (0xcd14)
+#define DWC3_RX_OOBS_SSC0      (0xcd18)
+#define DWC3_CMU_SSC1          (0xcd1C)
+#define DWC3_CMU_DEBUG_LDO     (0xcd20)
+#define DWC3_TX_AMP_DEBUG      (0xcd24)
+#define DWC3_Z0                (0xcd28)
+#define DWC3_DMR_BACR          (0xcd2C)
+#define DWC3_IER_BCSR          (0xcd30)
+#define DWC3_BPR               (0xcd34)
+#define DWC3_BFNR              (0xcd38)
+#define DWC3_BENR_REV          (0xcd3C)
+#define DWC3_FLD               (0xcd40)
+#define DWC3_CMU_PLL2_BISTDEBUG    (0xcd44)
+#define DWC3_USB2_P0_VDCTL     (0xcd48)
+#define DWC3_BACKDOOR          (0xcd4C)
+#define DWC3_EXT_CTL           (0xcd50)
+#define DWC3_EFUSE_CTR         (0xcd54)
+#define DWC3_GCTL               (0xc110)
+
+
+#define USB3_MOD_RST           (1 << 14)
+#define CMU_BIAS_EN            (1 << 20)
+
+
+#define BIST_QINIT(n)          ((n) << 24)
+#define EYE_HEIGHT(n)          ((n) << 20)
+#define PLL2_LOCK              (1 << 15)
+#define PLL2_RS(n)             ((n) << 12)
+#define PLL2_ICP(n)            ((n) << 10)
+#define CMU_SEL_PREDIV         (1 << 9)
+#define CMU_DIVX2              (1 << 8)
+#define PLL2_DIV(n)            ((n) << 3)
+#define PLL2_POSTDIV(n)        ((n) << 1)
+#define PLL2_PU                (1 << 0)
+
+#define DWC3_GCTL_CORESOFTRESET		(1 << 11)
+
+
+#define DWC3_GCTL_PRTCAP(n)       (((n) & (3 << 12)) >> 12)
+#define DWC3_GCTL_PRTCAPDIR(n)    ((n) << 12)
+#define DWC3_GCTL_PRTCAP_HOST     1
+#define DWC3_GCTL_PRTCAP_DEVICE   2
+#define DWC3_GCTL_PRTCAP_OTG	    3
+
+#define HOST_DETECT_STEPS          5
+#define DEVICE_DETECT_STEPS        5
+
+#define HOST_CONFIRM_STEPS         3
+#define DEVICE_CONFIRM_STEPS       4
+
+
+#define USB3_P0_CTL_VBUS_P0       5
+#define USB3_P0_CTL_ID_P0         11
+#define USB3_P0_CTL_DPPUEN_P0     14
+#define USB3_P0_CTL_DMPUEN_P0     15
+#define USB3_P0_CTL_DPPDDIS_P0    12
+#define USB3_P0_CTL_DMPDDIS_P0    13
+#define USB3_P0_CTL_SOFTIDEN_P0   8
+#define USB3_P0_CTL_SOFTID_P0     9
+#define USB3_P0_CTL_SOFTVBUSEN_P0 6
+#define USB3_P0_CTL_SOFTVBUS_P0   7
+#define USB3_P0_CTL_PLLLDOEN      28
+#define USB3_P0_CTL_LDOVREFSEL_SHIFT  29
+
+#define     USB3_P0_CTL_LDOVREFSEL_SHIFT_IC1                                      28
+#define     USB3_P0_CTL_PLLLDOEN_IC1                                              31
+
+#define USB3_P0_CTL_LS_P0_SHIFT   3
+#define USB3_P0_CTL_LS_P0_MASK    (0x3<<3)
+
+
+#define VBUS_THRESHOLD		3000 
+
+enum{
+   IC_ATM7039C = 0,
+   IC_ATM7059A
+};
+#define ANA00 (0+0xCD00)
+#define ANA01 (0+0xCD04)
+#define ANA02 (0+0xCD08)
+#define ANA03 (0+0xCD0C)
+#define ANA04 (0+0xCD10)
+
+#define ANA05 (0+0xCD14)
+#define ANA06 (0+0xCD18)
+#define ANA07 (0+0xCD1C)
+#define ANA08 (0+0xCD20)
+#define ANA09 (0+0xCD24)
+#define ANA0A (0+0xCD28)
+#define ANA0B (0+0xCD2C)
+#define ANA0C (0+0xCD30)
+#define ANA0D (0+0xCD34)
+#define ANA0E (0+0xCD38)
+#define ANA0F (0+0xCD3C)
+#define DMR (0+0xCD40)
+#define BACR (0+0xCD44)
+#define IER (0+0xCD48)
+#define BCSR (0+0xCD4C)
+#define BPR (0+0xCD50)
+#define BPNR2 (0+0xCD54)
+#define BFNR (0+0xCD58)
+#define BRNR2 (0+0xCD5C)
+#define BENR (0+0xCD60)
+#define REV0 (0+0xCD64)
+#define REV1 (0+0xCD68)
+#define REV2 (0+0xCD6C)
+#define REV3 (0+0xCD70)
+#define FLD0 (0+0xCD74)
+#define FLD1 (0+0xCD78)
+#define ANA1F (0+0xCD7C)
+#define PAGE1_REG00 (0+0xCD80)
+#define PAGE1_REG01 (0+0xCD84)
+#define PAGE1_REG02 (0+0xCD88)
+#define PAGE1_REG03 (0+0xCD8C)
+#define PAGE1_REG04 (0+0xCD90)
+#define PAGE1_REG05 (0+0xCD94)
+#define PAGE1_REG06 (0+0xCD98)
+#define PAGE1_REG07 (0+0xCD9C)
+#define PAGE1_REG08 (0+0xCDA0)
+#define PAGE1_REG09 (0+0xCDA4)
+#define PAGE1_REG0A (0+0xCDA8)
+#define PAGE1_REG0B (0+0xCDAC)
+#define PAGE1_REG0C (0+0xCDB0)
+#define PAGE1_REG0D (0+0xCDB4)
+#define PAGE1_REG0E (0+0xCDB8)
+#define PAGE1_REG0F (0+0xCDBC)
+#define PAGE1_REG10 (0+0xCDC0)
+#define USB2_P0_VDCTRL (0+0xCE00)
+#define BACKDOOR (0+0xCE04)
+#define EXT_CONTROL (0+0xCE08)
+#define EFUSE_CTR (0+0xCE0C)
+#define USB2_P1_VDCTRL (0+0xCE10) 
+
+#endif  /* __AOTG_REGS_H__ */
+ 
+
diff --git a/drivers/usb/monitor/umonitor_api.c b/drivers/usb/monitor/umonitor_api.c
new file mode 100644
index 0000000..b22c3ae
--- /dev/null
+++ b/drivers/usb/monitor/umonitor_api.c
@@ -0,0 +1,1341 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <linux/kthread.h>
+#include <mach/switch.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/wakelock.h>
+#include <linux/suspend.h>
+#include <linux/kallsyms.h>
+#include <linux/suspend.h>
+
+#include <mach/hardware.h>
+#include <mach/bootdev.h>
+
+#include <asm/uaccess.h>
+
+#include "umonitor_config.h"
+#include "umonitor_core.h"
+#include "aotg_regs.h"
+
+typedef void (*FUNC)(int);
+FUNC set_usb_plugin_type;
+
+#define CONNECT_USB_PORT	1
+#define CONNECT_USB_ADAPTOR	2
+
+
+struct delayed_work monitor_work;
+struct delayed_work monitor_resume_work;
+atomic_t wake_lock_atomic;
+unsigned int monitor_work_pending;
+unsigned int wake_lock_register_cnt;
+
+#if SUPPORT_NOT_RMMOD_USBDRV
+extern int dwc3_set_plugstate(int s);
+extern int xhci_set_plugstate(int s);
+
+enum plugstate{
+	PLUGSTATE_A_OUT=0,
+	PLUGSTATE_B_OUT,
+	PLUGSTATE_A_IN,
+	PLUGSTATE_B_IN,
+	PLUGSTATE_A_SUSPEND,
+	PLUGSTATE_A_RESUME,	
+	PLUGSTATE_B_SUSPEND,
+	PLUGSTATE_B_RESUME,	
+};
+#endif
+extern umonitor_dev_status_t *umonitor_status;
+
+struct mon_sysfs_status {
+	unsigned int charger_connected;
+	unsigned int pc_connected;
+	unsigned int udisk_connected;
+};
+
+struct port_dev {
+	struct switch_dev sdev;
+	char state_msg[64];
+};
+
+struct monitor_con {
+	unsigned int thread_chk_times;
+	int run;
+
+	spinlock_t lock;
+	struct mutex mon_mutex;
+	struct port_dev port_dev;
+	umon_port_config_t port_config;
+	umonitor_api_ops_t port_ops;
+	struct kobject *mon_obj;    /* just for sysfs. */
+	struct kobject *mon_port;
+	struct mon_sysfs_status port_status;
+
+	atomic_t port_exit;
+	struct task_struct *tsk;
+	wait_queue_head_t mon_wait;
+
+	volatile unsigned int det_plugin_req;
+	volatile unsigned int det_plugout_req;
+	struct timer_list port_timer;
+	struct timer_list check_timer;
+	struct wake_lock monitor_wake_lock;
+#if SUPPORT_NOT_RMMOD_USBDRV    
+	int dwc3_status;
+	int xhci_status;
+	int dwc3_timeout_cnt;
+	int xhci_timeout_cnt;
+	int (*dwc3_set_plugstate)(int s);
+	int (*xhci_set_plugstate)(int s);
+#endif    
+	void __iomem  *base;
+	int probe_fail;
+	int resume_status;
+};
+
+struct monitor_con monitor_mon_dev;
+static struct monitor_con *my_mon = &monitor_mon_dev;
+static unsigned long pm_status;
+
+static ssize_t mon_status_show(struct kobject *kobj,
+							   struct kobj_attribute *attr, char *buf);
+static ssize_t mon_config_show(struct kobject *kobj,
+							   struct kobj_attribute *attr, char *buf);
+static ssize_t mon_config_store(struct kobject *kobj,
+								struct kobj_attribute *attr, const char *instr, size_t bytes);
+
+#define ATTRCMP(x) (0 == strcmp(attr->attr.name, #x))
+#define MONITOR_ATTR_LIST(x)    (&x ## _attribute.attr)
+#define MON_STATUS_ATTR(x)  static struct kobj_attribute x##_attribute =   \
+    __ATTR(x, S_IRUGO, mon_status_show,  NULL)
+#define MON_CONFIG_ATTR(x)  static struct kobj_attribute x##_attribute =   \
+    __ATTR(x, (S_IRUGO|S_IWUSR), mon_config_show, mon_config_store)
+
+/* default just for usb port0. */
+static void mon_port_putt_msg(unsigned int msg);
+static int usb_detect_plugout_event(void);
+int usb_set_vbus_power(int value);
+static void monitor_resume_delay_work(struct work_struct *work);
+
+#ifdef SUPPORT_NOT_RMMOD_USBDRV    
+static void monitor_handle_plug_in_out_msg(char * usb_con_msg)
+{
+	if (!strncmp(usb_con_msg, "USB_B_IN", 8))
+	{
+		my_mon->dwc3_set_plugstate(PLUGSTATE_B_IN);
+		my_mon->xhci_set_plugstate(PLUGSTATE_B_IN);
+	}
+	else   if(!strncmp(usb_con_msg, "USB_B_OUT", 9))
+	{ 
+		my_mon->xhci_set_plugstate(PLUGSTATE_B_OUT);
+		my_mon->dwc3_set_plugstate(PLUGSTATE_B_OUT);
+	}
+	else   if(!strncmp(usb_con_msg, "USB_A_IN", 8))
+	{
+		my_mon->dwc3_set_plugstate(PLUGSTATE_A_IN);
+		my_mon->xhci_set_plugstate(PLUGSTATE_A_IN);
+	}
+	else   if(!strncmp(usb_con_msg, "USB_A_OUT", 9))
+	{
+		my_mon->xhci_set_plugstate(PLUGSTATE_A_OUT);
+		my_mon->dwc3_set_plugstate(PLUGSTATE_A_OUT);
+	}
+	else{
+		printk("usb monitor handle msg err! %s\n",usb_con_msg);        
+	}    
+}
+#endif
+/* check in and out message, and check whether it accordant with driver state. */
+static int usb_check_msg_and_drv_state(void)
+{
+	usb_hal_monitor_t *p_hal;
+	umonitor_dev_status_t *pStatus;
+	pStatus = umonitor_status;
+	p_hal = &umonitor_status->umonitor_hal;
+
+	my_mon->thread_chk_times++;
+	/* at system startup will do a plugout, make 5 seconds to detect usb status  
+	 * after that will modify the wrong status by checking udisk_connected & pc_connected
+	 */
+	if (my_mon->thread_chk_times <5) {	
+		return 0;
+	}
+
+	if (my_mon->port_status.udisk_connected == 0) {
+		if ((my_mon->xhci_status == PLUGSTATE_A_IN) || 
+		    (my_mon->xhci_status == PLUGSTATE_A_SUSPEND) || 
+		    (my_mon->xhci_status == PLUGSTATE_A_RESUME)) {
+			my_mon->xhci_timeout_cnt++;
+			goto mon_adjust_state;
+		}
+	} else {
+		if (my_mon->xhci_status != PLUGSTATE_A_IN) {
+			my_mon->xhci_timeout_cnt++;
+			goto mon_adjust_state;
+		}
+	}
+
+	if (my_mon->port_status.pc_connected == 0) {
+		if (my_mon->dwc3_status == PLUGSTATE_B_IN) {
+			my_mon->dwc3_timeout_cnt++;
+			goto mon_adjust_state;
+		}
+	} else {
+		if (my_mon->dwc3_status != PLUGSTATE_B_IN) {
+			my_mon->dwc3_timeout_cnt++;
+			goto mon_adjust_state;
+		}
+	}
+	return 0;
+
+mon_adjust_state:
+	printk("xhci_status:%d, dwc3:%d\n", my_mon->xhci_status, my_mon->dwc3_status);
+	printk("udisk_con:%d, pc:%d\n", my_mon->port_status.udisk_connected, my_mon->port_status.pc_connected);
+
+	/* process host unnormal state. */
+	if (my_mon->xhci_status == PLUGSTATE_A_SUSPEND) {
+		p_hal->suspend_or_resume(p_hal, 0);
+		my_mon->dwc3_set_plugstate(PLUGSTATE_A_RESUME);
+		my_mon->xhci_set_plugstate(PLUGSTATE_A_RESUME);
+		wake_lock_timeout(&my_mon->monitor_wake_lock, 12*HZ);
+		printk("----now lock for 12*HZ\n");
+	}
+	if (my_mon->port_status.udisk_connected == 0) {
+		if ((my_mon->xhci_status == PLUGSTATE_A_IN) || (my_mon->xhci_status == PLUGSTATE_A_RESUME)) {
+			if (my_mon->xhci_timeout_cnt > 4) {
+				printk("%s:%d! \n", __func__, __LINE__);
+				my_mon->xhci_timeout_cnt = 0;
+				my_mon->xhci_set_plugstate(PLUGSTATE_A_OUT);
+				my_mon->dwc3_set_plugstate(PLUGSTATE_A_OUT);
+				umonitor_detection(1);
+			}
+		}
+	} else {
+		if (my_mon->xhci_status != PLUGSTATE_A_IN) {
+			if (my_mon->xhci_timeout_cnt > 10) {
+				printk("%s:%d! \n", __func__, __LINE__);
+				my_mon->xhci_timeout_cnt = 0;
+				pStatus->core_ops->putt_msg(MON_MSG_USB_A_OUT);
+				pStatus->message_status &= ~(0x1 << MONITOR_A_IN);
+				//umonitor_core_resume();
+				umonitor_detection(1);
+			}
+		}
+	}
+
+	/* process device unnormal state. */
+	if (my_mon->port_status.pc_connected == 0) {
+		if (my_mon->dwc3_status == PLUGSTATE_B_IN) {
+			if (my_mon->dwc3_timeout_cnt > 10) {
+				printk("%s:%d! \n", __func__, __LINE__);
+				my_mon->dwc3_timeout_cnt = 0;
+				pStatus->core_ops->putt_msg(MON_MSG_USB_B_OUT);
+				pStatus->message_status &= ~(0x1 << MONITOR_B_IN);
+				//my_mon->xhci_set_plugstate(PLUGSTATE_B_OUT);
+				//my_mon->dwc3_set_plugstate(PLUGSTATE_B_OUT);
+				umonitor_detection(1);
+			}
+		}
+	} else {
+		if (my_mon->dwc3_status != PLUGSTATE_B_IN) {
+			if (my_mon->dwc3_timeout_cnt > 10) {
+				printk("%s:%d! \n", __func__, __LINE__);
+				my_mon->dwc3_timeout_cnt = 0;
+				pStatus->core_ops->putt_msg(MON_MSG_USB_B_OUT);
+				pStatus->message_status &= ~(0x1 << MONITOR_B_IN);
+				umonitor_detection(1);
+			}
+		}
+	}
+
+	return 1;
+}
+
+static int mon_thread_port(void *data)
+{
+	unsigned int mtime = 0;
+ 
+	while (!kthread_should_stop() && (atomic_read(&my_mon->port_exit) == 0)) {
+
+		if (my_mon->run == 0) {
+			wait_event_interruptible(my_mon->mon_wait, my_mon->run);
+		}
+		wait_event_interruptible(my_mon->mon_wait, (my_mon->det_plugin_req != 0) ||
+							   kthread_should_stop() ||
+							   (my_mon->det_plugout_req != 0));
+		mutex_lock(&my_mon->mon_mutex);
+
+		if (usb_check_msg_and_drv_state()) {
+			spin_lock(&my_mon->lock);
+			if (my_mon->det_plugout_req) {
+				my_mon->det_plugout_req = 0;
+				mod_timer(&my_mon->check_timer, jiffies+ (CHECK_TIMER_INTERVAL*HZ)/2000 + (CHECK_TIMER_INTERVAL*HZ)/1000);
+			}
+			if (my_mon->det_plugin_req) {
+				my_mon->det_plugin_req = 0;
+				mod_timer(&my_mon->port_timer, jiffies+ 3+(CHECK_TIMER_INTERVAL*HZ)/2000 + (CHECK_TIMER_INTERVAL*HZ)/1000);
+			}
+			spin_unlock(&my_mon->lock);
+			mutex_unlock(&my_mon->mon_mutex);
+			continue;
+		}
+
+		if (my_mon->det_plugout_req == 1) {
+			usb_detect_plugout_event();
+			my_mon->det_plugout_req = 0;
+			mutex_unlock(&my_mon->mon_mutex);
+			continue;
+		}
+
+		if (my_mon->det_plugin_req) {
+			umonitor_timer_func();
+			mtime = umonitor_get_timer_step_interval();
+			spin_lock(&my_mon->lock);
+			mod_timer(&my_mon->port_timer, jiffies+(mtime*HZ)/1000);
+			my_mon->det_plugin_req = 0;
+			spin_unlock(&my_mon->lock);
+			mutex_unlock(&my_mon->mon_mutex);
+			continue;
+		}
+	}
+
+	/* mon_thread_port0 already exited */
+	MONITOR_PRINTK("monitor: mon_thread_port0 is going to exit.\n");
+	atomic_set(&my_mon->port_exit, 0);
+	return 0;
+}
+
+static void mon_timer_func_port(unsigned long h)
+{
+	if (!spin_trylock(&my_mon->lock)) {
+		MONITOR_PRINTK("timer0 my_mon->lock unavailable!\n");
+		mod_timer(&my_mon->port_timer, jiffies+1);
+		return;
+	}
+	my_mon->det_plugin_req = 1;
+	spin_unlock(&my_mon->lock);
+	wake_up(&my_mon->mon_wait);
+	return;
+}
+
+static void mon_timer_func_check(unsigned long h)
+{
+	if (!spin_trylock(&my_mon->lock)) {
+		mod_timer(&my_mon->check_timer, jiffies+1);
+		return;
+	}
+	my_mon->det_plugout_req = 1;
+	spin_unlock(&my_mon->lock);
+	wake_up(&my_mon->mon_wait);
+	return;
+}
+
+static ssize_t umonitor_switch_state(struct switch_dev *sdev, char *buf)
+{
+	struct port_dev *port_dev = container_of(sdev, struct port_dev, sdev);
+	return sprintf(buf, "%s\n",port_dev->state_msg);
+}
+
+/*release wake lock*/
+static void monitor_release_wakelock(struct work_struct *work)
+{
+	if (wake_lock_register_cnt > 0) {
+		wake_lock_register_cnt--;
+		printk("\n monitor_release_wakelock  wake_unlock  %d-\n",wake_lock_register_cnt);
+		wake_unlock(&my_mon->monitor_wake_lock);;
+	}
+}
+
+
+#ifdef CONFIG_OF
+
+struct monitor_data{
+    int ic_type;
+};
+static  struct monitor_data  atm7039c_data = {
+	.ic_type = IC_ATM7039C,
+
+};
+
+static  struct monitor_data  atm7059a_data = {
+	.ic_type = IC_ATM7059A,
+};
+
+static const struct of_device_id  owl_monitor_of_match[]   = {
+	{.compatible = "actions,atm7039c-usbmonitor", .data = &atm7039c_data},
+	{.compatible = "actions,atm7059tc-usbmonitor", .data = &atm7059a_data },
+	{.compatible = "actions,atm7059a-usbmonitor", .data = &atm7059a_data },
+	{}
+
+};
+MODULE_DEVICE_TABLE(of, owl_monitor_of_match);
+#else
+static void monitor_release(struct device *dev)
+{
+	MONITOR_PRINTK("monitor_release\n");
+}
+
+static struct platform_device monitor_device = {
+	.name = "usb_monitor",
+	.id = -1,
+	.num_resources = 0,
+	.resource = NULL,
+	.dev = {
+		.release = monitor_release,
+	},
+};
+#endif
+static int get_configuration_from_dts(struct of_device_id *id )
+{
+	int ret = 0;
+	struct device_node *fdt_node;
+	const char *pp;
+	enum of_gpio_flags flags;
+	umon_port_config_t *port_config = &my_mon->port_config;
+
+	fdt_node = of_find_compatible_node(NULL, NULL,  id->compatible);
+	if (NULL == fdt_node) {
+		printk("<umonitor>err: no usb3-fdt-compatible [%s]\n",  id->compatible);
+		goto DEFAULT_SETTING;
+	}
+
+	pp = of_get_property(fdt_node, "detect_type", NULL);
+	if (!pp) {
+		printk("<umonitor>err: no config detect_type!use default value:UMONITOR_HOST_AND_DEVICE\n");
+		port_config->detect_type = UMONITOR_HOST_AND_DEVICE;
+	}else{
+		port_config->detect_type = be32_to_cpup((const __be32 *)pp);
+	}
+
+	pp = of_get_property(fdt_node, "idpin_type", NULL);
+	if (!pp) {
+		printk("<umonitor>err: no config idpin_type!use default value:UMONITOR_USB_IDPIN\n");
+		port_config->idpin_type = UMONITOR_USB_IDPIN;
+	}else{
+		port_config->idpin_type = be32_to_cpup((const __be32 *)pp); 
+	}
+
+	if(port_config->idpin_type == UMONITOR_GPIO_IDPIN){
+		if (of_find_property(fdt_node, "idpin_gpio", NULL)){
+			port_config->idpin_gpio_no = of_get_named_gpio_flags(fdt_node, "idpin_gpio",0, &flags);	        
+			if (gpio_request(port_config->idpin_gpio_no,  id->compatible)){                   		
+				printk("<umonitor>err: fail to request idpin gpio [%d]\n", port_config->idpin_gpio_no);
+				port_config->idpin_gpio_no = -1;
+				return -1;	                	
+			}else{
+				gpio_direction_input(port_config->idpin_gpio_no);
+				printk("<umonitor> : idpin_type is GPIO_IDPIN, gpio_no=%d\n",port_config->idpin_gpio_no);
+			}
+		}else{
+			port_config->idpin_type = UMONITOR_USB_IDPIN;	
+			printk("<umonitor>err : idpin_type is GPIO_IDPIN,but can't find idpin gpio,set idpin_type = UMONITOR_USB_IDPIN\n");		            
+		}
+
+	}
+
+	pp = of_get_property(fdt_node, "vbus_type", NULL);
+	if (!pp) {
+		printk("<umonitor>err: no config vbus_type!use default value:UMONITOR_DC5V_VBUS\n");
+		port_config->vbus_type = UMONITOR_DC5V_VBUS;
+	}else{
+		port_config->vbus_type = be32_to_cpup((const __be32 *)pp); 
+	}
+
+	if (!of_find_property(fdt_node, "vbus_otg_en_gpios", NULL)) {
+		printk("<umonitor>err: no config vbus_otg_engpio!\n");
+		port_config->power_switch_gpio_no = 0xffff;		 
+		port_config->power_switch_active_level = 1;	 
+		goto REQUEST_OTG_VBUS;
+	}
+	port_config->power_switch_gpio_no = of_get_named_gpio_flags(fdt_node,  "vbus_otg_en_gpios",0, &flags);
+	port_config->power_switch_active_level = flags & OF_GPIO_ACTIVE_LOW;
+
+	REQUEST_OTG_VBUS:
+
+	printk("====otgvbus_gpio: num-%d, active-%s---detect_type=%d,idpin_type=%d,vbus_type=%d---\n",\
+	port_config->power_switch_gpio_no, port_config->power_switch_active_level ? "high" : "low",port_config->detect_type,\
+	port_config->idpin_type,port_config->vbus_type);
+	if (gpio_request(port_config->power_switch_gpio_no,  id->compatible)) {		
+		printk("<umonitor>err: fail to request vbus gpio [%d]\n", port_config->power_switch_gpio_no);
+		port_config->power_switch_gpio_no = 0xffff;
+		return 0;
+	}
+	//power gpio oupru, power switch off
+	gpio_direction_output(port_config->power_switch_gpio_no, !port_config->power_switch_active_level);
+	gpio_set_value_cansleep(port_config->power_switch_gpio_no, !port_config->power_switch_active_level);
+
+	return ret;
+
+	DEFAULT_SETTING:
+	printk("<umonitor>err: use default setting... \n" );
+	port_config->detect_type = UMONITOR_HOST_AND_DEVICE;
+	port_config->idpin_type = UMONITOR_USB_IDPIN;
+	port_config->vbus_type = UMONITOR_DC5V_VBUS;
+	port_config->power_switch_gpio_no = 0xffff;		
+	port_config->power_switch_active_level = 1;   
+	goto REQUEST_OTG_VBUS;
+}
+
+
+static int s_dwc3_set_plugstate(int s)
+{
+	int ret;
+    
+	my_mon->dwc3_timeout_cnt = 0;
+	if (my_mon->dwc3_status == s)
+		return 0;
+	my_mon->dwc3_status = s;
+	if(s == PLUGSTATE_A_OUT){
+		lock_system_sleep();
+		wake_lock_timeout(&my_mon->monitor_wake_lock, 10*HZ);
+		unlock_system_sleep();
+		ret = dwc3_set_plugstate(s);
+		return ret;
+	}
+	else {
+		return dwc3_set_plugstate(s);
+	}
+}
+
+static int s_xhci_set_plugstate(int s)
+{
+	my_mon->xhci_timeout_cnt = 0;
+	if (my_mon->xhci_status == s)
+		return 0;
+	my_mon->xhci_status = s;
+	return xhci_set_plugstate(s);
+}
+
+static int monitor_probe(struct platform_device *_dev)
+{
+	int ret = 0;
+	void __iomem  *base;
+	struct monitor_data *monitor_owl;
+	struct of_device_id *id = (struct of_device_id *)of_match_device(owl_monitor_of_match, &_dev->dev);
+        
+	if(id ==NULL)
+	{
+		printk("<umonitor>err: get dts fail !! \n");
+		ret= -EINVAL;
+		goto	err_monitor_probe_fail;
+	}
+    
+	monitor_owl =(struct monitor_data *) id->data;
+	platform_set_drvdata(_dev, monitor_owl);
+	ret = get_configuration_from_dts(id );
+
+	if (ret != 0)
+		goto	err_monitor_probe_fail;
+
+	/*init &my_mon->lock */
+	spin_lock_init(&my_mon->lock);
+	mutex_init(&my_mon->mon_mutex);
+	my_mon->thread_chk_times = 0;
+	my_mon->run = 0;
+	my_mon->tsk = NULL;
+
+	/* status init. */
+	my_mon->port_status.charger_connected = 0;
+	my_mon->port_status.pc_connected = 0;
+	my_mon->port_status.udisk_connected = 0;
+
+	my_mon->port_config.idpin_debug = 0xff;   
+	my_mon->port_config.vbus_debug = 0xff; 
+	/*
+	  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	    if (!res) {
+	        printk("missing memory base resource\n");
+	        return -EINVAL;
+	    }
+
+	  base = devm_ioremap(dev, res->start, resource_size(res));
+	*/
+
+	base = (void __iomem *)IO_ADDRESS(USB3_REGISTER_BASE);
+	if (!base) {
+		MONITOR_ERR("ioremap failed\n");
+		my_mon->port_config.port_type = PORT_DWC3;
+		ret = -ENOMEM;
+		goto	err_monitor_probe_fail;
+	}
+#if SUPPORT_NOT_RMMOD_USBDRV
+        my_mon->dwc3_status = -1;
+        my_mon->xhci_status = -1;
+        my_mon->dwc3_timeout_cnt = 0;
+        my_mon->xhci_timeout_cnt = 0;
+        my_mon->dwc3_set_plugstate = s_dwc3_set_plugstate;
+        my_mon->xhci_set_plugstate = s_xhci_set_plugstate;
+#endif
+
+	my_mon->base = base;
+	MONITOR_PRINTK("my_mon->base is %08x\n",(unsigned int )my_mon->base);
+
+	ret = umonitor_core_init(&my_mon->port_ops, &my_mon->port_config, (unsigned int)my_mon->base);
+	if (ret != 0)
+		goto	err_monitor_probe_fail;
+		
+   	umonitor_status->umonitor_hal.ic_type = monitor_owl->ic_type;
+	/* add for switch device. */
+	my_mon->port_dev.sdev.name = "monitor_dev";
+	my_mon->port_dev.sdev.print_state = umonitor_switch_state;
+	ret = switch_dev_register(&my_mon->port_dev.sdev);
+	if (ret < 0) {
+		MONITOR_ERR("failed to register switch dev0 in umonitor. \n");
+		goto err_monitor_probe_fail;
+	}
+
+	/*WAKE_LOCK_SUSPEND Ϊsuspend lock\A3\AC\BB\B9\D3\D0һ\D6\D6idle lock*/
+	MONITOR_PRINTK(KERN_EMERG"%s--%d, initalize a wake_lock\n", __FILE__, __LINE__);
+	wake_lock_init(&my_mon->monitor_wake_lock, WAKE_LOCK_SUSPEND, "usb_monitor");
+
+	init_waitqueue_head(&my_mon->mon_wait);
+	my_mon->det_plugin_req = 0;
+
+	my_mon->tsk =
+		kthread_create(mon_thread_port, NULL, "usb_monitor");
+
+	if (IS_ERR(my_mon->tsk)) {
+		ret = PTR_ERR(my_mon->tsk);
+		my_mon->tsk = NULL;
+		MONITOR_ERR("err: create monitor thread failed\n");
+		goto out;
+	}
+	wake_up_process(my_mon->tsk);
+	/*register timer and function "mon_timer_func"*/
+	setup_timer(&my_mon->port_timer, mon_timer_func_port, 0);
+	my_mon->port_timer.expires = jiffies + HZ/2;
+	add_timer(&my_mon->port_timer);
+
+	setup_timer(&my_mon->check_timer, mon_timer_func_check, 0);
+	my_mon->check_timer.expires = jiffies + HZ/2;
+	add_timer(&my_mon->check_timer);
+
+	monitor_work_pending =0;
+	wake_lock_register_cnt =0;
+	INIT_DELAYED_WORK(&monitor_work, monitor_release_wakelock);
+    	INIT_DELAYED_WORK(&monitor_resume_work, monitor_resume_delay_work);
+#ifdef CONFIG_USB_PLATFORM_LINUX	
+	if(owl_get_boot_mode() != OWL_BOOT_MODE_UPGRADE){
+		umonitor_detection(1); 
+		my_mon->dwc3_status = PLUGSTATE_B_IN;
+		umonitor_status->message_status |= 0x1 << MONITOR_B_IN;
+		my_mon->port_status.pc_connected = 1;
+		my_mon->port_status.charger_connected = CONNECT_USB_PORT;
+		umonitor_status->detect_valid = 0;	//disable detection	
+		my_mon->run = 1;
+	}
+#endif  
+	my_mon->resume_status = -1;
+	return 0;
+out:
+	switch_dev_unregister(&my_mon->port_dev.sdev);
+err_monitor_probe_fail:
+	my_mon->probe_fail =1;
+	return ret;
+}
+
+static int __exit monitor_remove(struct platform_device *_dev)
+{
+	del_timer_sync(&my_mon->port_timer);
+	del_timer_sync(&my_mon->check_timer);
+    	cancel_delayed_work_sync(&monitor_resume_work);
+	//wake_unlock(&my_mon->monitor_wake_lock);
+	wake_lock_destroy(&my_mon->monitor_wake_lock);
+
+	/* wait for mon_thread exit */
+	if (my_mon->tsk != NULL) {
+		atomic_set(&my_mon->port_exit, 1);
+		kthread_stop(my_mon->tsk);
+	}
+
+	msleep(2);
+	if (atomic_read(&my_mon->port_exit) != 0) {
+		MONITOR_ERR("error unable to stop mon_thread_port\n");
+	}
+	my_mon->tsk = NULL;
+
+	switch_dev_unregister(&my_mon->port_dev.sdev);
+	MONITOR_PRINTK("monitor driver remove successufully\n");
+	return 0;
+}
+
+static int monitor_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	unsigned int mtime;
+
+	if (pm_status == PM_HIBERNATION_PREPARE) {
+		return 0;
+	}
+	my_mon->resume_status = 0;
+    
+	/*
+	usb charger plugin will triger PLUGSTATE_B_IN	;
+	if usb charger plugin &battery is full,will go into suspend.
+	So here need to plugout before suspend;
+	*/
+	if (my_mon->xhci_status == PLUGSTATE_A_IN) {
+		my_mon->xhci_set_plugstate(PLUGSTATE_A_SUSPEND);
+		my_mon->dwc3_set_plugstate(PLUGSTATE_A_SUSPEND);
+	}
+	if (my_mon->dwc3_status == PLUGSTATE_B_IN) {
+		my_mon->xhci_set_plugstate(PLUGSTATE_B_SUSPEND);
+		my_mon->dwc3_set_plugstate(PLUGSTATE_B_SUSPEND);
+	}
+	mtime = 0x70000000;
+	umonitor_core_suspend();
+
+	//delay timer for a long time;may reset timer in resume
+	mod_timer(&my_mon->port_timer, jiffies+(mtime*HZ)/1000);
+	mod_timer(&my_mon->check_timer, jiffies+(mtime*HZ)/1000);
+
+	return 0;
+}
+
+static void monitor_resume_delay_work(struct work_struct *work)
+{
+	umonitor_core_resume();
+	/*mod timer*/
+	mod_timer(&my_mon->port_timer, jiffies+(3100*HZ)/1000);
+	mod_timer(&my_mon->check_timer, jiffies+(4*CHECK_TIMER_INTERVAL*HZ)/1000);
+}
+
+static int monitor_resume(struct platform_device *pdev)
+{
+	my_mon->resume_status = 1; 
+	if (pm_status == PM_HIBERNATION_PREPARE) {
+		return 0;
+	}   
+	/*in android ,will close controller through vold,so usb device driver is ready*/    
+#ifndef CONFIG_USB_PLATFORM_LINUX 		    
+    	umonitor_core_resume();
+	/*mod timer*/
+	mod_timer(&my_mon->port_timer, jiffies+(3100*HZ)/1000);
+	mod_timer(&my_mon->check_timer, jiffies+(4*CHECK_TIMER_INTERVAL*HZ)/1000);
+#endif    
+	return 0;
+}
+
+static void monitor_shutdown(struct platform_device *pdev)
+{
+	umonitor_core_suspend();
+}
+
+static struct platform_driver monitor_driver = {
+	.probe = monitor_probe,
+	.remove = monitor_remove,
+	.suspend = monitor_suspend,
+	.resume = monitor_resume,
+	.shutdown = monitor_shutdown,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "usb_monitor",
+		.of_match_table = owl_monitor_of_match,
+	},
+};
+
+static int monitor_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy)
+{
+	unsigned int mtime = 0x70000000;
+
+	if (event == PM_HIBERNATION_PREPARE) {
+		pm_status = PM_HIBERNATION_PREPARE;
+		umonitor_core_suspend();
+		//delay timer for a long time;may reset timer in resume
+		mod_timer(&my_mon->port_timer, jiffies+(mtime*HZ)/1000);
+		mod_timer(&my_mon->check_timer, jiffies+(mtime*HZ)/1000);
+	} else if (event == PM_POST_HIBERNATION) {
+		pm_status = 0;
+		MONITOR_PRINTK(KERN_INFO "monitor resume!\n");
+		umonitor_core_resume();
+		/*mod timer*/
+		mod_timer(&my_mon->port_timer, jiffies+(500*HZ)/1000);
+		mod_timer(&my_mon->check_timer, jiffies+(CHECK_TIMER_INTERVAL*HZ)/1000);
+	}
+	/*in ubuntu ,will close controller after resume finish,so usb device driver is ready*/    
+#ifdef CONFIG_USB_PLATFORM_LINUX 			
+	if(event ==PM_POST_SUSPEND){
+		printk("\n monitor_pm_notify %d\n",__LINE__);
+		if(my_mon->resume_status == 1)        
+        		schedule_delayed_work(&monitor_resume_work, msecs_to_jiffies(500));		
+        }
+#endif
+	return NOTIFY_OK;
+}
+
+static struct notifier_block monitor_pm_notifier = {
+	.notifier_call = monitor_pm_notify,
+};
+
+#if 0
+static int owl_hibernate_notifier_event(struct notifier_block *this,
+		unsigned long event, void *ptr)
+{
+
+	switch (event) {
+		case PM_HIBERNATION_PREPARE:
+        //umonitor_dwc_otg_init();
+			break;
+		case PM_POST_HIBERNATION:       //\B5ڶ\FE\B4ο\AA\BB\FAʱ\A3\AC\B3ɹ\A6\BBָ\B4\B5\BD\B5\DAһ\B4ιػ\FA\B5\C4״̬ʱ\B5\F7\D3\C3
+			break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block owl_hibernate_notifier = {
+	.notifier_call = owl_hibernate_notifier_event,
+};
+#endif
+
+#if  1              /* add sysfs info. */
+MON_STATUS_ATTR(charger_connected);
+MON_STATUS_ATTR(pc_connected);
+MON_STATUS_ATTR(udisk_connected);
+
+MON_CONFIG_ATTR(run);
+MON_CONFIG_ATTR(detect_type);
+MON_CONFIG_ATTR(port_type);
+/* for idpin config. */
+MON_CONFIG_ATTR(idpin_type);
+MON_CONFIG_ATTR(idpin_gpio_group);
+MON_CONFIG_ATTR(idpin_gpio_no);
+/* for vbus config. */
+MON_CONFIG_ATTR(vbus_type);
+MON_CONFIG_ATTR(vbus_gpio_group);
+MON_CONFIG_ATTR(vbus_gpio_no);
+/* in host state, if vbus power switch onoff use gpio, set it. */
+MON_CONFIG_ATTR(power_switch_gpio_group);
+MON_CONFIG_ATTR(power_switch_gpio_no);
+MON_CONFIG_ATTR(power_switch_active_level);
+MON_CONFIG_ATTR(idpin_debug);
+MON_CONFIG_ATTR(vbus_debug);
+#ifdef SUPPORT_NOT_RMMOD_USBDRV     
+MON_CONFIG_ATTR(usb_con_msg);
+#endif
+static struct attribute *mon_status_attrs[] = {
+	MONITOR_ATTR_LIST(charger_connected),
+	MONITOR_ATTR_LIST(pc_connected),
+	MONITOR_ATTR_LIST(udisk_connected),
+	NULL,           /* terminator */
+};
+
+static struct attribute_group mon_port_status = {
+	.name = "status",
+	.attrs = mon_status_attrs,
+};
+
+static struct attribute *mon_config_attrs[] = {
+	MONITOR_ATTR_LIST(run),
+	MONITOR_ATTR_LIST(detect_type),
+	MONITOR_ATTR_LIST(port_type),
+	/* for idpin config. */
+	MONITOR_ATTR_LIST(idpin_type),
+	MONITOR_ATTR_LIST(idpin_gpio_group),
+	MONITOR_ATTR_LIST(idpin_gpio_no),
+	/* for vbus config. */
+	MONITOR_ATTR_LIST(vbus_type),
+	MONITOR_ATTR_LIST(vbus_gpio_group),
+	MONITOR_ATTR_LIST(vbus_gpio_no),
+	/* in host state, if vbus power switch onoff use gpio, set it. */
+	MONITOR_ATTR_LIST(power_switch_gpio_group),
+	MONITOR_ATTR_LIST(power_switch_gpio_no),
+	MONITOR_ATTR_LIST(power_switch_active_level),
+	MONITOR_ATTR_LIST(idpin_debug),
+	MONITOR_ATTR_LIST(vbus_debug),	
+#ifdef SUPPORT_NOT_RMMOD_USBDRV     	
+	MONITOR_ATTR_LIST(usb_con_msg),
+#endif	
+	NULL,           /* terminator */
+};
+
+static struct attribute_group mon_port_config = {
+	.name = "config",
+	.attrs = mon_config_attrs,
+};
+
+
+static ssize_t mon_status_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	struct mon_sysfs_status *p_status;
+    
+    	if(my_mon->probe_fail ==1){
+		printk("\n monitor: probe_fail =1!!");
+        	return -ENOENT;
+	}
+	if (kobj == my_mon->mon_port) {
+		p_status = &my_mon->port_status;
+	} else {
+		return -ENOENT;
+	}
+
+	if (ATTRCMP(charger_connected)) {
+		return sprintf(buf, "%d\n", p_status->charger_connected);
+	} else if (ATTRCMP(pc_connected)) {
+		return sprintf(buf, "%d\n", p_status->pc_connected);
+	} else if (ATTRCMP(udisk_connected)) {
+		return sprintf(buf, "%d\n", p_status->udisk_connected);
+	} else {
+	}
+	return -ENOENT;
+}
+
+static ssize_t mon_config_show(struct kobject *kobj,
+							   struct kobj_attribute *attr, char *buf)
+{
+	umon_port_config_t *pconfig;
+    
+    	if(my_mon->probe_fail ==1){
+		printk("\n  monitor: probe_fail =1!!");
+        	return -ENOENT;
+	}
+	if (kobj == my_mon->mon_port) {
+		pconfig = &my_mon->port_config;
+	} else {
+		return -ENOENT;
+	}
+
+	if (ATTRCMP(run)) {
+		//return sprintf(buf, "%d\n", umonitor_get_run_status());
+		return sprintf(buf, "%d\n", my_mon->run);
+	} else if(ATTRCMP(detect_type)) {
+		return sprintf(buf, "%d\n", pconfig->detect_type);
+	} else if(ATTRCMP(idpin_type)) {
+		return sprintf(buf, "%d\n", pconfig->idpin_type);
+    } else if(ATTRCMP(port_type)) {
+        *buf = pconfig->port_type;
+        return sizeof(char);
+	} else if(ATTRCMP(idpin_gpio_group)) {
+		return sprintf(buf, "%d\n", pconfig->idpin_gpio_group);
+	} else if(ATTRCMP(idpin_gpio_no)) {
+		return sprintf(buf, "%d\n", pconfig->idpin_gpio_no);
+	} else if(ATTRCMP(vbus_type)) {
+		return sprintf(buf, "%d\n", pconfig->vbus_type);
+	} else if(ATTRCMP(vbus_gpio_group)) {
+		return sprintf(buf, "%d\n", pconfig->vbus_gpio_group);
+	} else if(ATTRCMP(vbus_gpio_no)) {
+		return sprintf(buf, "%d\n", pconfig->vbus_gpio_no);
+	}else if(ATTRCMP(power_switch_gpio_group)) {
+		return sprintf(buf, "%d\n", pconfig->power_switch_gpio_group);
+	} else if(ATTRCMP(power_switch_gpio_no)) {
+		return sprintf(buf, "%d\n", pconfig->power_switch_gpio_no);
+	} else if(ATTRCMP(power_switch_active_level)) {
+		return sprintf(buf, "%d\n", pconfig->power_switch_active_level);
+	}else if(ATTRCMP(idpin_debug)) {
+		return sprintf(buf, "%d\n", pconfig->idpin_debug);
+	}else if(ATTRCMP(vbus_debug)) {
+		return sprintf(buf, "%d\n", pconfig->vbus_debug);
+	} 
+#ifdef SUPPORT_NOT_RMMOD_USBDRV         
+    	else if(ATTRCMP(usb_con_msg)) {
+		return sprintf(buf, "%s\n", pconfig->usb_con_msg);
+	}
+#endif        
+        else {
+		/* do nothing. */
+	}
+
+	return -ENOENT;
+}
+
+static ssize_t mon_config_store(struct kobject *kobj, struct kobj_attribute *attr, const char *instr, size_t bytes)
+{
+	unsigned long val;
+	unsigned int ret, plugstatus;
+	umon_port_config_t *pconfig;
+    
+    	if(my_mon->probe_fail ==1){
+		printk("\n monitor: probe_fail =1!!");
+        	return -ENOENT;
+	}
+	mutex_lock(&my_mon->mon_mutex);
+
+	if (kobj == my_mon->mon_port) {
+		pconfig = &my_mon->port_config;
+	} else {
+		MONITOR_PRINTK("store no err!\n");
+		goto out;
+	}
+
+	ret = kstrtoul(instr, 0, &val);
+	MONITOR_PRINTK("kstrtoul:%d\n", (unsigned int)val);
+
+	if (ATTRCMP(run)) {
+		my_mon->run = val;
+		if(val == 1) {
+#ifndef CONFIG_USB_PLATFORM_LINUX 		
+			umonitor_detection(val); 
+#endif		        
+		} else if (val == 2) {
+			MONITOR_PRINTK("vbus on off\n");
+			usb_set_vbus_power(0);
+			mdelay(500);
+			plugstatus = umonitor_get_message_status();
+			if( (plugstatus & (0x1 << MONITOR_A_IN)) !=0)
+				usb_set_vbus_power(1);
+
+		} else if (val == 3) {
+			mon_port_putt_msg(MON_MSG_USB_B_OUT);
+		} else if (val == 4) {
+			mon_port_putt_msg(MON_MSG_USB_B_IN);
+		} else if (val == 5) {
+#ifndef CONFIG_USB_PLATFORM_LINUX		
+#if SUPPORT_NOT_RMMOD_USBDRV            
+			my_mon->dwc3_set_plugstate(PLUGSTATE_B_OUT);
+			my_mon->xhci_set_plugstate(PLUGSTATE_B_OUT);
+#endif   
+#endif   
+		}else {
+		}
+	} else if(ATTRCMP(detect_type)) {
+		pconfig->detect_type = val;
+	} else if(ATTRCMP(idpin_type)) {
+		pconfig->idpin_type = val;
+	} else if(ATTRCMP(idpin_gpio_group)) {
+		pconfig->idpin_gpio_group = val;
+	} else if(ATTRCMP(idpin_gpio_no)) {
+		pconfig->idpin_gpio_no = val;
+	} else if(ATTRCMP(vbus_type)) {
+		pconfig->vbus_type = val;
+	} else if(ATTRCMP(vbus_gpio_group)) {
+		pconfig->vbus_gpio_group = val;
+	} else if(ATTRCMP(vbus_gpio_no)) {
+		pconfig->vbus_gpio_no = val;
+	} else if(ATTRCMP(power_switch_gpio_group)) {
+		pconfig->power_switch_gpio_group = val;
+	} else if(ATTRCMP(power_switch_gpio_no)) {
+		pconfig->power_switch_gpio_no = val;
+	} else if(ATTRCMP(power_switch_active_level)) {
+		/* backdoor for debug. */
+		if (val == 2) {
+			umonitor_printf_debuginfo();
+		}else{
+			pconfig->power_switch_active_level = val;
+		}
+	}else if(ATTRCMP(idpin_debug)) {
+		pconfig->idpin_debug = val;
+        	if((val ==0)||(val ==1))
+			printk("\n debug idpin set =%d !!\n",pconfig->idpin_debug);         
+		else
+			printk("\n debug idpin clear!!\n");
+	}else if(ATTRCMP(vbus_debug)) {
+		pconfig->vbus_debug = val;
+		if((val ==0)||(val ==1))
+			printk("\n debug vbus set =%d!!\n",pconfig->vbus_debug);  
+		else
+			printk("\n debug vbus clear!!\n");
+	} 
+#ifndef CONFIG_USB_PLATFORM_LINUX    
+#ifdef SUPPORT_NOT_RMMOD_USBDRV    
+    	else if(ATTRCMP(usb_con_msg)) {
+		strcpy(pconfig->usb_con_msg,instr);
+		monitor_handle_plug_in_out_msg(instr);     
+		printk("\n write usb_con_msg %s\n",instr);
+	}
+#endif        
+#endif        
+        else {
+		/* do nothing. */
+		MONITOR_PRINTK("store attr err!\n");
+	}
+
+out:
+	mutex_unlock(&my_mon->mon_mutex);
+	return bytes;
+}
+
+int mon_sysfs_init(void)
+{
+	int ret = 0;
+
+	my_mon->mon_obj = kobject_create_and_add("monitor", NULL);
+	if (!my_mon->mon_obj) {
+		MONITOR_ERR("unable to create monitor kobject\n");
+	}
+	my_mon->mon_port = kobject_create_and_add("usb_port", my_mon->mon_obj);
+	if (!my_mon->mon_port) {
+		MONITOR_ERR("unable to create usb_port kobject\n");
+	}
+
+	ret = sysfs_create_group(my_mon->mon_port, &mon_port_status);
+	if (ret != 0) {
+		MONITOR_ERR("create usb_port status group failed\n");
+	}
+	ret = sysfs_create_group(my_mon->mon_port, &mon_port_config);
+	if (ret != 0) {
+		MONITOR_ERR("create usb_port cofig group failed\n");
+	}
+	/* ignore failed case. */
+	return 0;
+}
+
+int mon_sysfs_exit(void)
+{
+	sysfs_remove_group(my_mon->mon_port, &mon_port_status);
+	sysfs_remove_group(my_mon->mon_port, &mon_port_config);
+	kobject_del(my_mon->mon_port);
+	kobject_del(my_mon->mon_obj);
+	return 0;
+}
+#endif              /* add sysfs info. */
+
+static int usb_detect_plugout_event(void)
+{
+	usb_hal_monitor_t * p_hal;
+	unsigned int val;
+	unsigned int message;
+	int ret;
+    
+	p_hal = &umonitor_status->umonitor_hal;
+	message = umonitor_status->message_status;
+
+	if(umonitor_status->detect_valid == 0) {
+
+		if (umonitor_status->det_phase == 0) {
+			if(((message & (0x1 << MONITOR_B_IN)) != 0) ||
+			   ((message & (0x1 << MONITOR_CHARGER_IN)) != 0)) {
+				if(( my_mon->port_status.charger_connected == CONNECT_USB_ADAPTOR) && 
+				   (wake_lock_register_cnt > 0)) {
+					printk("wakelock release!!!!!!!!\n");
+					wake_lock_register_cnt--;
+					wake_unlock(&my_mon->monitor_wake_lock);
+				}
+				umonitor_status->vbus_status = (unsigned char) p_hal->get_vbus_state(p_hal);
+				ret = p_hal->get_idpin_state(p_hal);
+				if((umonitor_status->vbus_status == USB_VBUS_LOW)||(ret==USB_ID_STATE_HOST)) {
+					my_mon->port_status.charger_connected = 0;
+					umonitor_detection(1);
+					printk("\n========usb_detect_plugout_event===start det!!========\n");
+					//wake_up(&my_mon->mon_wait);
+				}
+			}
+		} else {
+			/*host set monitor flag*/
+			if((message & (0x1 << MONITOR_A_IN)) != 0) {
+				val = p_hal->get_idpin_state(p_hal);
+				if(val != USB_ID_STATE_HOST) {
+					umonitor_detection(1);
+					//wake_up(&my_mon->mon_wait);
+				}
+			}
+		}
+
+		mod_timer(&my_mon->check_timer, jiffies + (CHECK_TIMER_INTERVAL*HZ)/1000);
+	} else {
+		mod_timer(&my_mon->check_timer, jiffies + 3 + (2 * CHECK_TIMER_INTERVAL * HZ)/1000);
+	}
+
+	return 0;
+}
+
+int notify_driver_state(int driver_state, int driver_type)
+{
+	return 0;
+}
+EXPORT_SYMBOL(notify_driver_state);
+
+static void mon_port_wakeup_func(void)
+{
+	my_mon->det_plugin_req = 1;
+	wake_up(&my_mon->mon_wait);
+	return;
+}
+
+static void mon_port_putt_msg(unsigned int msg)
+{
+	struct mon_sysfs_status * pStatus;
+	usb_hal_monitor_t *p_hal;
+	
+	pStatus = &my_mon->port_status;
+	p_hal = &umonitor_status->umonitor_hal;
+
+	switch (msg) {
+		case MON_MSG_USB_B_IN:
+			//printk("%s--%d, wake_lock !!! \n", __FILE__, __LINE__);
+			if(monitor_work_pending == 1) {
+				cancel_delayed_work_sync(&monitor_work);
+				monitor_work_pending = 0;
+			}
+			if(!wake_lock_register_cnt) {
+				printk("%s--%d, wake_lock !!! \n", __FILE__, __LINE__);
+				wake_lock(&my_mon->monitor_wake_lock);
+				wake_lock_register_cnt++;
+			}
+			pStatus->pc_connected = 1;
+			pStatus->charger_connected = CONNECT_USB_PORT;//set usb pc first,it'll jude by dwc3 interrupt
+			sprintf(my_mon->port_dev.state_msg, "USB_B_IN");
+			
+#ifdef CONFIG_USB_PLATFORM_LINUX
+			monitor_handle_plug_in_out_msg(my_mon->port_dev.state_msg);//handle usb msg in monitor
+#else
+			switch_set_state(&my_mon->port_dev.sdev, msg);			    //handle usb msg through vold
+#endif            
+			break;
+		case MON_MSG_USB_B_OUT:
+			//printk("%s--%d, wake_unlock !!! \n", __FILE__, __LINE__);
+			if(wake_lock_register_cnt) {
+				schedule_delayed_work(&monitor_work, msecs_to_jiffies(1000));
+				monitor_work_pending = 1;
+			}
+			pStatus->pc_connected = 0;
+			pStatus->charger_connected = 0;
+			sprintf(my_mon->port_dev.state_msg, "USB_B_OUT");
+#ifdef CONFIG_USB_PLATFORM_LINUX
+			monitor_handle_plug_in_out_msg(my_mon->port_dev.state_msg);//handle usb msg in monitor
+#else
+			switch_set_state(&my_mon->port_dev.sdev, msg);			    //handle usb msg through vold
+#endif    
+			break;
+		case MON_MSG_USB_A_IN:
+			pStatus->udisk_connected = 1;
+			printk("%s--%d, wake_lock !!! \n", __FILE__, __LINE__);
+			//wake_lock(&my_mon->monitor_wake_lock);
+			sprintf(my_mon->port_dev.state_msg, "USB_A_IN");
+#ifdef CONFIG_USB_PLATFORM_LINUX
+			monitor_handle_plug_in_out_msg(my_mon->port_dev.state_msg);//handle usb msg in monitor
+#else
+			switch_set_state(&my_mon->port_dev.sdev, msg);			    //handle usb msg through vold
+#endif    
+			wake_lock_timeout(&my_mon->monitor_wake_lock, 10*HZ);
+			printk("----monitor_wake_lock for 10s \n");
+			break;
+		case MON_MSG_USB_A_OUT:
+			pStatus->udisk_connected = 0;
+			printk("%s--%d, wake_unlock !!! \n", __FILE__, __LINE__);
+			//wake_unlock(&my_mon->monitor_wake_lock);
+			sprintf(my_mon->port_dev.state_msg, "USB_A_OUT");
+#ifdef CONFIG_USB_PLATFORM_LINUX
+			monitor_handle_plug_in_out_msg(my_mon->port_dev.state_msg);//handle usb msg in monitor
+#else
+			switch_set_state(&my_mon->port_dev.sdev, msg);			    //handle usb msg through vold
+#endif    
+			wake_lock_timeout(&my_mon->monitor_wake_lock, 10*HZ);
+			break;
+		case MON_MSG_USB_CHARGER_IN:
+			pStatus->charger_connected = 1;
+			//printk("%s--%d, wake_lock !!! \n", __FILE__, __LINE__);
+			wake_lock(&my_mon->monitor_wake_lock);
+			sprintf(my_mon->port_dev.state_msg, "USB_CHARGER_IN");
+#ifdef CONFIG_USB_PLATFORM_LINUX
+			monitor_handle_plug_in_out_msg(my_mon->port_dev.state_msg);//handle usb msg in monitor
+#else
+			switch_set_state(&my_mon->port_dev.sdev, msg);			    //handle usb msg through vold
+#endif    
+			break;
+		case MON_MSG_USB_CHARGER_OUT:
+			pStatus->charger_connected = 0;
+			printk("%s--%d, wake_unlock !!! \n", __FILE__, __LINE__);
+			wake_unlock(&my_mon->monitor_wake_lock);
+			sprintf(my_mon->port_dev.state_msg, "USB_CHARGER_OUT");
+#ifdef CONFIG_USB_PLATFORM_LINUX
+			monitor_handle_plug_in_out_msg(my_mon->port_dev.state_msg);//handle usb msg in monitor
+#else
+			switch_set_state(&my_mon->port_dev.sdev, msg);			    //handle usb msg through vold
+#endif    
+			break;
+		default:
+			MONITOR_ERR("err msg:%0x\n", msg);
+			break;
+	}
+	return;
+}
+
+int usb_set_vbus_power(int value)
+{
+	return umonitor_vbus_power_onoff(value);
+}
+EXPORT_SYMBOL_GPL(usb_set_vbus_power);
+
+void monitor_set_usb_plugin_type(int value)
+{
+	my_mon->port_status.charger_connected = value;
+	/*  when connect to pc, some reason make pc send reset interrupt at a long time later,
+	 *  at this point maybe we have released wakelock;so we get wakelock again here!
+	 */    	
+	if((wake_lock_active(&my_mon->monitor_wake_lock)==false)&&(value==CONNECT_USB_PORT)&&(my_mon->run==1)){
+		printk("\n usb reset interrupt,get wakelock!!\n");
+		wake_lock_register_cnt=1;
+		wake_lock(&my_mon->monitor_wake_lock);
+	}
+}
+EXPORT_SYMBOL_GPL(monitor_set_usb_plugin_type);
+static int __init monitor_init(void)
+{
+	int ret;
+
+	atomic_set(&my_mon->port_exit, 0);
+
+	my_mon->port_ops.wakeup_func = mon_port_wakeup_func;
+	my_mon->port_ops.putt_msg = mon_port_putt_msg;
+	my_mon->probe_fail =0;
+#ifndef CONFIG_OF
+	ret = platform_device_register(&monitor_device);
+	if (ret < 0) {
+		MONITOR_ERR("Can't register monitor platform device, ret:%d\n", ret);
+	}
+#endif
+
+	ret = platform_driver_register(&monitor_driver);
+	if (ret < 0) {
+		MONITOR_ERR("monitor driver register failed,err is %d\n", ret);
+	}
+	/*create director "/sys/monitor", "/sys/usb_port" and attribute file: */
+	ret = mon_sysfs_init();
+	if (ret < 0) {
+		MONITOR_ERR("mon_sysfs_init failed,err is %d\n", ret);
+	}
+
+	set_usb_plugin_type = (FUNC )kallsyms_lookup_name("atc260x_set_usb_plugin_type");
+	register_pm_notifier(&monitor_pm_notifier);
+	//register_hibernate_notifier(&owl_hibernate_notifier);
+
+	return ret;
+}
+
+static void __exit monitor_exit(void)
+{
+	//unregister_hibernate_notifier(&owl_hibernate_notifier);
+	unregister_pm_notifier(&monitor_pm_notifier);
+	platform_driver_unregister(&monitor_driver);
+#ifndef CONFIG_OF
+	platform_device_unregister(&monitor_device);
+#endif
+
+	umonitor_core_exit();
+
+	mon_sysfs_exit();
+
+	gpio_free(my_mon->port_config.power_switch_gpio_no);
+
+	MONITOR_PRINTK("end of monitor_exit\n");
+	return;
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("houjingkun");
+
+late_initcall_sync(monitor_init);
+module_exit(monitor_exit);
+
diff --git a/drivers/usb/monitor/umonitor_config.h b/drivers/usb/monitor/umonitor_config.h
new file mode 100644
index 0000000..03bfaea
--- /dev/null
+++ b/drivers/usb/monitor/umonitor_config.h
@@ -0,0 +1,108 @@
+/*! \cond USBMONITOR*/
+/*********************************************************************************
+*                            Module: usb monitor driver
+*                (c) Copyright 2003 - 2008, Actions Co,Ld. 
+*                        All Right Reserved 
+*
+* History:        
+*      <author>      <time>       <version >    <desc>
+*       houjingkun   2011/07/08   1.0         build this file 
+********************************************************************************/ 
+/*!
+ * \file   umonitor_config.h
+ * \brief  
+ *      usb monitor configure headfile.
+ * \author houjingkun
+ * \par GENERAL DESCRIPTION:
+ * \par EXTERNALIZED FUNCTIONS:
+ *       null
+ *
+ *  Copyright(c) 2008-2012 Actions Semiconductor, All Rights Reserved.
+ *
+ * \version 1.0
+ * \date  2011/07/08
+ *******************************************************************************/
+#ifndef _UMONITOR_CONFIG_H_
+#define _UMONITOR_CONFIG_H_
+#define  SUPPORT_NOT_RMMOD_USBDRV 1
+//#ifdef ATM7029_EVB
+//#define GPIO_VBUS_SUPPLY    0x28      //KS_OUT1 GPIOB8   001  01000
+//#endif
+//
+//#ifdef ATM7029_DEMO
+//#define GPIO_VBUS_SUPPLY    0x11      //RMII_RXER GPIPA17 010 10001
+//#endif
+
+#define CHECK_TIMER_INTERVAL  1000
+
+
+#define __GPIO_GROUP(x)     ((x) >> 5)
+#define __GPIO_NUM(x)       ((x) & 0x1f)
+
+typedef struct umon_port_config {
+    #define UMONITOR_DISABLE   		   0
+    #define UMONITOR_DEVICE_ONLY       	   1
+    #define UMONITOR_HOST_ONLY	           2
+    #define UMONITOR_HOST_AND_DEVICE       3
+    unsigned char detect_type;	/* usb port detect request. */
+    /* if detect_type == UMONITOR_DISABLE, below is no use. */
+    
+    unsigned char port_type;
+	#define PORT_DWC3   		   0
+	#define PORT_USB2       	   1    
+    
+
+    #define UMONITOR_USB_IDPIN   	   0
+    #define UMONITOR_SOFT_IDPIN       	   1
+    #define UMONITOR_GPIO_IDPIN	           2  /* gpio detect idpin. */
+    unsigned char idpin_type;
+    /*
+     * if idpin_type set to UMONITOR_USB_IDPIN or UMONITOR_SOFT_IDPIN, 
+     * below is no use. 
+     */
+    unsigned char idpin_gpio_group;
+    unsigned int idpin_gpio_no;
+
+    #define UMONITOR_USB_VBUS   	   0
+    #define UMONITOR_GPIO_VBUS	           1  /* gpio detect vbus. */
+    #define UMONITOR_DC5V_VBUS             2  /* use dc5v to detect vbus. */
+    unsigned char vbus_type;
+    /*
+     * if vbus_type set to UMONITOR_USB_VBUS, below is no use. 
+     */
+    unsigned char vbus_gpio_group;
+    unsigned int vbus_gpio_no;
+
+    /* in host state, if vbus power switch onoff use gpio, set it. */
+    unsigned char power_switch_gpio_group;
+    unsigned int power_switch_gpio_no;
+    unsigned char power_switch_active_level;
+#ifdef SUPPORT_NOT_RMMOD_USBDRV      
+    /* add a node to receive vold msg ,to open close controlers */
+    char usb_con_msg[32];
+#endif
+    /*add a node to fix idpin&vbus state, let user can detect host/device as wish*/	
+    unsigned char idpin_debug;
+    unsigned char vbus_debug;	
+} umon_port_config_t;
+
+
+	
+//#define 	DEBUG_MONITOR
+//#define   ERR_MONITOR
+	
+#ifdef DEBUG_MONITOR
+#define MONITOR_PRINTK(fmt, args...)    printk(KERN_INFO fmt, ## args)
+#else
+#define MONITOR_PRINTK(fmt, args...)    /*not printk*/
+#endif
+
+#ifdef ERR_MONITOR
+#define MONITOR_ERR(fmt, args...)    printk(KERN_ERR fmt, ## args)
+#else
+#define MONITOR_ERR(fmt, args...)    /*not printk*/
+#endif	
+		
+#endif  /* _UMONITOR_CONFIG_H_ */
+/*! \endcond*/
+
diff --git a/drivers/usb/monitor/umonitor_core.c b/drivers/usb/monitor/umonitor_core.c
new file mode 100644
index 0000000..d768a7b
--- /dev/null
+++ b/drivers/usb/monitor/umonitor_core.c
@@ -0,0 +1,1016 @@
+/*********************************************************************************
+*                            Module: usb monitor driver
+*                (c) Copyright 2003 - 2008, Actions Co,Ld. 
+*                        All Right Reserved 
+*
+* History:        
+*      <author>      <time>       <version >    <desc>
+*       houjingkun   2011/07/08   1.0         build this file 
+********************************************************************************/
+/*!
+ * \file   umonitor_core.c
+ * \brief  
+ *      usb monitor detect opration code.
+ * \author houjingkun
+ * \par GENERAL DESCRIPTION:
+ * \par EXTERNALIZED FUNCTIONS:
+ *       null
+ *
+ *  Copyright(c) 2008-2012 Actions Semiconductor, All Rights Reserved.
+ *
+ * \version 1.0
+ * \date  2011/07/08
+ *******************************************************************************/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include <linux/kthread.h>
+#include <linux/completion.h>
+#include <linux/poll.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/ctype.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include "aotg_regs.h"
+#include "umonitor_config.h"
+#include "umonitor_core.h"
+
+
+enum {
+	USB_DET_NONE = 0,	/* nothing detected, maybe B plus is out. */
+	USB_DET_DEVICE_DEBUOUNCING,	/* detected device, debouncing and confirming. */
+	USB_DET_DEVICE_PC,	/* detected device confirmed. pc connected. */
+	USB_DET_DEVICE_CHARGER	/* detected device confirmed. charger connected. */
+};
+
+enum {
+	USB_DET_HOST_NONE = 0,	/* nothing detected. maybe udisk is plug out. */
+	USB_DET_HOST_DEBOUNCING,	/* detecting host, debouncing and confirming. */
+	USB_DET_HOST_UDISK	/* detected udisk confirmed. udisk connected. */
+};
+
+#define USB_DEVICE_DETECT_STEPS    4
+#define USB_HOST_DETECT_STEPS      4
+#define USB_MONITOR_DEF_INTERVAL   500	/* interval to check usb port state, unit: ms. */
+
+umonitor_dev_status_t *umonitor_status;
+static int usb_monitor_debug_status_inf( void )
+{
+#if 0
+	umonitor_dev_status_t *pStatus = umonitor_status;
+
+	printk(KERN_INFO ".det_phase %d %d %d %d %d \n",
+	       (unsigned int) pStatus->det_phase,
+	       (unsigned int) pStatus->vbus_status,
+	       (unsigned int) pStatus->timer_steps,
+	       (unsigned int) pStatus->host_confirm,
+	       (unsigned int) pStatus->message_status);
+	printk(KERN_INFO "-----------------------------\n");
+	printk(KERN_INFO ".vbus_status %d %x \n", (unsigned int) pStatus->vbus_status,
+	       (unsigned int) pStatus->vbus_status);
+	printk(KERN_INFO ".vbus_enable_power %d\n", (unsigned int) pStatus->vbus_enable_power);
+	printk(KERN_INFO ".det_phase %d \n", (unsigned int) pStatus->det_phase);
+	printk(KERN_INFO ".device_confirm %d\n", (unsigned int) pStatus->device_confirm);
+	printk(KERN_INFO ".host_confirm %d \n", (unsigned int) pStatus->host_confirm);
+	printk(KERN_INFO ".usb_pll_on %d \n", (unsigned int) pStatus->usb_pll_on);
+	printk(KERN_INFO ".dp_dm_status %d 0x%x \n", (unsigned int) pStatus->dp_dm_status,
+	       (unsigned int) pStatus->dp_dm_status);
+	printk(KERN_INFO ".timer_steps %d \n", (unsigned int) pStatus->timer_steps);
+	printk(KERN_INFO ".timer_interval %d \n", (unsigned int) pStatus->timer_interval);
+	printk(KERN_INFO ".check_cnt %d \n", (unsigned int) pStatus->check_cnt);
+	printk(KERN_INFO ".sof_check_times %d\n", (unsigned int) pStatus->sof_check_times);
+	printk(KERN_INFO "\n \n ");
+#endif
+	return 0;
+}
+
+static int usb_init_monitor_status(umonitor_dev_status_t * pStatus)
+{
+  
+	pStatus->detect_valid = 0;
+	pStatus->detect_running = 0;
+	pStatus->vbus_status = 0;
+	pStatus->dc5v_status = 0;
+	pStatus->det_phase = 0;
+	pStatus->device_confirm = 0;
+	pStatus->sof_check_times = 0;
+	pStatus->host_confirm = 0;
+	pStatus->usb_pll_on = 0;
+	pStatus->dp_dm_status = 0;
+	pStatus->timer_steps = 0;
+	pStatus->timer_interval = USB_MONITOR_DEF_INTERVAL;
+	pStatus->check_cnt = 0;
+	pStatus->message_status = 0;
+	pStatus->core_ops = NULL;
+		
+	pStatus->vbus_enable_power = 0;
+	
+	return 0;
+}
+
+/* \BB\F1ȡ\D4\CB\D0е\BD\CF\C2һ\B4μ\EC\B2\E2\B5\C4ʱ\BC\E4\BC\E4\B8\F4\A3\AC\B7\B5\BB\D8ֵ\D2Ժ\C1\C3\EBΪ\B5\A5λ\A1\A3 */
+unsigned int umonitor_get_timer_step_interval(void)
+{
+	umonitor_dev_status_t *pStatus;
+
+	pStatus = umonitor_status;
+
+	if ((pStatus->port_config->detect_type == UMONITOR_DISABLE)
+		|| (pStatus->detect_valid == 0)) {
+		return 0x70000000;	/* be longer enough that it would not run again. */
+	}
+
+	if (pStatus->timer_steps == 0) {
+		//pStatus->timer_interval = USB_MONITOR_DEF_INTERVAL;
+		pStatus->timer_interval = 30;	/*\D6\D8\D0½\F8\C8\EBstep 0 \BC\EC\B2\E9 */
+		goto out;
+	}
+
+	if (pStatus->det_phase == 0) {
+		switch (pStatus->timer_steps) {
+			/* 
+			 * 1\A3\AD3\B2\BD\A3\AC\BC\EC\B2\E2ʱ\BC\E4\BC\E4\B8\F4500 ms\A3\A8\BFɵ\F7\D5\FB\A3\A9\A3\ACһ\B5\A9\B6˿\DA\D3б仯\C2\ED\C9ϵ\F7\B5\BD\B5\DA\CBIJ\BD\A3\AC
+			 * \BD\F8\C8\EBdebounce\BA\CDconfirm״̬\A1\A3
+			 */
+		case 1:
+		case 2:
+		case 3:
+			pStatus->timer_interval = USB_MONITOR_DEF_INTERVAL;
+			break;
+
+		case 4:
+			switch (pStatus->device_confirm) {
+			case 0:	/* \BD\F8\C8\EB\B5\DA4\B2\BD\A3\AC\CF\C2һ\B2\BD\CAǼ\EC\B2\E2\B6˿\DAvbus\D3\D0\CEޱ仯\A1\A3 */
+				pStatus->timer_interval =
+				    USB_MONITOR_DEF_INTERVAL;
+				break;
+
+			case 1:	/* \D2Ѿ\AD\BC\EC\B2⵽\B6˿\DAvbus\D3е磬\D0\E8Ҫ\CF\C2һ\B2\BD\D4\D9ȷ\C8\CFһ\B4Ρ\A3 */
+				pStatus->timer_interval = 10;	/* 10 ms, 1 tick. */
+				break;
+
+				/*
+				 * device_confirm == 2, \D2Ѿ\ADȷ\C8\CFvbus\D3е磬\B2\A2enable\C9\CF\C0\AD500k\A3\AC
+				 * disable\CF\C2\C0\AD15k\A3\AC\CF\C2һ\B2\BD\BC\EC\B2\E2dp\A1\A2dm״̬\A1\A3 
+				 */
+			case 2:
+				pStatus->timer_interval = 300;
+				break;
+
+				/* \B5\DAһ\B4λ\F1ȡdp\A1\A2dm״̬\A3\AC\D0\E8Ҫ\CF\C2һ\B4\CE\D4\D9ȷ\C8\CFһ\B4Ρ\A3 */
+			case 3:
+				pStatus->timer_interval = 30;
+				break;
+
+				/* 
+				 * \BD\F8\C8\EB\D5\E2һ\B2\BD\A3\AC\D0\E8Ҫ\B6\E0\B4\CE\C5ж\CFpc\CAǷ\F1\D3\D0sof\BB\F2reset\D0źŸ\F8С\BB\FA\A3\AC\D5\E2\C0\EFÿ20\BA\C1\C3\EB\B2\E9ѯsof\D6ж\CFһ\B4Σ\AC
+				 * \C0ۻ\FD\BB\E1\B2\E9ѯ MAX_DETECT_SOF_CNT \B4Σ\AC\B5ȴ\FDʱ\BC\E4\BF\C9\C4ܻ\E1\D3\D08\C3\EB\D2\D4\C9ϡ\A3 
+				 * \D2\F2Ϊ\B4\D3С\BB\FAdp\C9\CF\C0\AD\B5\BDpc\B7\A2sof\A3\AC\D6м\E4\BF\C9\C4\DC\D1\D3ʱ\B3\A4\B4\EF8\C3\EB\D2\D4\C9ϡ\A3
+				 */
+				/* wait sof again time interval, the whole detect sof time is (20 * sof_check_times) msecond. */
+			case 4:
+				pStatus->timer_interval = 20;
+				break;
+
+			default:
+				USB_ERR_PLACE;
+				pStatus->timer_interval =
+				    USB_MONITOR_DEF_INTERVAL;
+				break;
+			}
+			break;
+
+		default:
+			USB_ERR_PLACE;
+			pStatus->timer_interval = USB_MONITOR_DEF_INTERVAL;
+			break;
+		}
+	} else {
+		switch (pStatus->timer_steps) {
+		case 1:	/* \B4\D3step 0\B5\C4idle״̬\C7л\BB\B5\BDvbus\B6\D4\CD⹩\B5\E7\B5\C4ʱ\BC\E4\BC\E4\B8\F4\A1\A3 */
+			pStatus->timer_interval = 30;
+			break;
+
+		case 2:	/* vbus\B6\D4\CD⹩\B5\E7\BA󣬵\BD\BF\AAʼ\B5\DA2\B4μ\EC\B2⣬\C5ж\CFdp\CAǷ\F1\C9\CF\C0\AD\B5\C4ʱ\BC䡣 */
+			pStatus->timer_interval = 600;
+			break;
+
+		case 3:	/* \B5\DA2\B4μ\EC\B2⵽\B5\DA3\B4μ\EC\B2\E2֮\BC䣬\C5ж\CFdp\CAǷ\F1\C9\CF\C0\AD\B5\C4ʱ\BC䡣 */
+			pStatus->timer_interval = 600;
+			break;
+
+		case 4:
+			switch (pStatus->host_confirm) {
+			case 0:
+				pStatus->timer_interval =
+				    USB_MONITOR_DEF_INTERVAL;
+				break;
+
+			case 1:	/* debounce time. */
+				pStatus->timer_interval = 10;	/* 10 ms, 1 tick. */
+				break;
+
+			default:
+				USB_ERR_PLACE;
+				pStatus->timer_interval =
+				    USB_MONITOR_DEF_INTERVAL;
+				break;
+			}
+			break;
+
+		default:
+			USB_ERR_PLACE;
+			pStatus->timer_interval = USB_MONITOR_DEF_INTERVAL;
+			break;
+		}
+	}
+
+out:
+	return pStatus->timer_interval;
+}
+
+/* 
+ * retval:
+ * refer to below macro:
+ *    USB_DET_NONE,
+ *    USB_DET_DEVICE_DEBUOUNCING,
+ *    USB_DET_DEVICE_PC,
+ *    USB_DET_DEVICE_CHARGER,  
+ */
+static int usb_timer_det_pc_charger(umonitor_dev_status_t * pStatus)
+{
+	int ret = 0;
+	unsigned int val = 0;
+	usb_hal_monitor_t *p_hal = &pStatus->umonitor_hal;
+	
+	MONITOR_PRINTK("entring usb_timer_det_pc_charger\n");
+
+	if (pStatus->device_confirm == 0) {
+		/* make sure power off. */
+		if (pStatus->vbus_enable_power != 0) {
+			p_hal->vbus_power_onoff(p_hal, 0);
+			pStatus->vbus_enable_power = 0;
+			p_hal->set_soft_id(p_hal, 1, 1);
+		}
+	}
+
+	pStatus->vbus_status = (unsigned char) p_hal->get_vbus_state(p_hal);
+
+	if (pStatus->vbus_status == USB_VBUS_HIGH) {
+      MONITOR_PRINTK("vbus is high!!!!!!!\n");
+		/* 
+		 * if B_IN is send out, needn't check device at all. 
+		 * \CE\D2\C3\C7ֻ\B4\A6\C0\ED\CFȲ\E5\C8\EB\B3\E4\B5\E7\C6\F7\B5\C4\C7\E9\BF\F6\CF£\AC\BC\EC\B2\E2pc\B5\C4\C1\AC\BDӺͶϿ\AA\A1\A3\C8\E7\B9\FB\CF\C8\C1\AC\BD\D3pc\A3\AC\D4\F2\B6\D4\D3ڳ\E4\B5\E7\C6\F7\B5IJ\E5\B0μ\EC\B2ⲻ\C1ˡ\A3
+		 */
+		if ((pStatus->message_status & (0x1 << MONITOR_B_IN)) != 0) {
+#if 0
+			/*
+			 * \B4˶δ\FA\C2뱾Ϊ\BC\EC\B2\E2Բ\BFڳ\E4\B5\E7\C6\F7\BA\CDpcͬʱ\B2\E5\C8\EB\B5\C4\C7\E9\BF\F6\CF¼\EC\B2\E2pc\B5İ\CE\CFߣ\AC\B5\ABʵ\BC\CA\C9ϴ\E6\D4\DA\CE\F3\C5ж\CFpc\B0\CE\CFߵ\C4\C7\E9\BF\F6\A3\AC
+			 * \D2\F2Ϊpc\B5\C4sof\BF\C9\C4\DC\D4ڶ\E0\B4η\A2\CB\CDδ\B9\FB\BA\F3һ\B6\CEʱ\BC\E4\C4ڲ\BB\D4ٷ\A2\CB͡\A3
+			 */
+			/* if pc is connected, and charger is new plug in, we ignore it. */
+			if ((pStatus->message_status &
+			     (0x1 << MONITOR_CHARGER_IN)) == 0)
+#endif
+			pStatus->device_confirm = 0;
+			pStatus->timer_steps = 0;
+			ret = USB_DET_DEVICE_PC;
+			goto out2;
+		}
+		if ((pStatus->message_status & (0x1 << MONITOR_CHARGER_IN)) != 0) {
+			pStatus->device_confirm = 0;
+			pStatus->timer_steps = 0;
+			ret = USB_DET_DEVICE_CHARGER;
+			goto out2;
+		}
+
+		switch (pStatus->device_confirm) {
+			/* \BD\F8\C8\EB\B5\DA4\B2\BD\A3\AC\BC\EC\B2⵽\B6˿\DAvbus\D3е硣\D6\C1\C9\D9deboundceһ\B4Σ\ACȷ\B1\A3\BC\EC\B2\E2\D5\FDȷ\A1\A3 */
+		case 0:
+			pStatus->timer_steps = USB_DEVICE_DETECT_STEPS;	/* the last timer_steps is to confirm. */
+			pStatus->device_confirm = 1;
+			ret = USB_DET_DEVICE_DEBUOUNCING;
+			goto out2;
+
+			/* \D2Ѿ\ADȷ\C8\CFvbus\D3е磬\B2\A2enable\C9\CF\C0\AD500k\A3\ACdisable\CF\C2\C0\AD15k\A3\AC\CF\C2һ\B2\BD\BC\EC\B2\E2dp\A1\A2dm״̬\A1\A3 */
+		case 1:
+			p_hal->set_dp_500k_15k(p_hal, 1, 0);	/* 500k up enable, 15k down disable; */
+			pStatus->device_confirm = 2;
+			ret = USB_DET_DEVICE_DEBUOUNCING;
+			goto out2;
+
+			/* \B5\DAһ\B4λ\F1ȡdp\A1\A2dm״̬\A3\AC\D0\E8Ҫ\D4\D9ȷ\C8\CFһ\B4Ρ\A3 */
+		case 2:
+			pStatus->dp_dm_status = p_hal->get_linestates(p_hal);	// get dp dm status.
+			pStatus->device_confirm = 3;
+			//pStatus->device_confirm = 2;  /* always in get dp dm states, just for test. */
+			ret = USB_DET_DEVICE_DEBUOUNCING;
+			goto out2;
+
+			/* 
+			 * \B5ڶ\FE\B4λ\F1ȡdp\A1\A2dm״̬\A3\AC\C8\E7\B9\FB\C1\BD\B4β\BB\B1䣬\D4\F2ȷ\C8\CFok\A3\AC\B7\F1\D4\F2\BD\F8һ\B2\BDdebounce\A1\A3
+			 * dp\BA\CDdm\B7\C70״̬Ϊ\B3\E4\B5\E7\C6\F7\A3\AC\B7\B4֮\BD\F8һ\B2\BD\C5ж\CFsof\D6ж\CFλ\BF\B4\BF\B4\CAǷ\F1pc\A1\A3
+			 */
+		case 3:
+			val = p_hal->get_linestates(p_hal);	// get dp dm status.
+			pStatus->sof_check_times = 0;
+			if (val == pStatus->dp_dm_status) {
+				if (val == 0x00) {
+					pStatus->timer_steps = 0;
+					pStatus->device_confirm = 0;
+					ret = USB_DET_DEVICE_PC;
+					
+					goto out2;
+				} else {
+					pStatus->device_confirm = 0;
+					/* if enable monitor again, it should begin from step 0.  */
+					pStatus->timer_steps = 0;
+					ret = USB_DET_DEVICE_PC;
+					goto out2;
+				}
+			} else {
+				pStatus->device_confirm = 1;
+				ret = USB_DET_DEVICE_DEBUOUNCING;
+				goto out2;
+			}
+
+			/* 
+			 * \BD\F8\C8\EB\D5\E2һ\B2\BD\A3\AC\D0\E8Ҫ\B6\E0\B4\CE\C5ж\CFpc\CAǷ\F1\D3\D0sof\BB\F2reset\D0źŸ\F8С\BB\FA\A3\AC
+			 * \B5ȴ\FDʱ\BC\E4\BF\C9\C4ܻ\E1\D3\D08\C3\EB\D2\D4\C9ϡ\A3 \D2\F2Ϊ\B4\D3С\BB\FAdp\C9\CF\C0\AD\B5\BDpc\B7\A2sof\A3\AC\D6м\E4\BF\C9\C4\DC\D1\D3ʱ\B3\A4\B4\EF8\C3\EB\D2\D4\C9ϡ\A3
+			 */
+			/* for detect sof or reset irq. */
+		case 4:
+			val = p_hal->is_sof(p_hal);
+			if (val != 0) {
+				/* if enable monitor again, it should begin from step 0. */
+				pStatus->timer_steps = 0;
+				pStatus->device_confirm = 0;
+				pStatus->sof_check_times = 0;
+				p_hal->dp_down(p_hal);
+				ret = USB_DET_DEVICE_PC;
+				goto out2;
+			}
+			if (pStatus->sof_check_times < MAX_DETECT_SOF_CNT) {	/* 10 * MAX_DETECT_SOF_CNT ms. */
+				pStatus->device_confirm = 4;	/* next step still check again. */
+				pStatus->sof_check_times++;
+				ret = USB_DET_DEVICE_DEBUOUNCING;
+				goto out2;
+			}
+
+			/* if enable monitor again, it should begin from step 0. */
+			pStatus->timer_steps = 0;
+			pStatus->device_confirm = 0;
+			pStatus->sof_check_times = 0;
+			p_hal->dp_down(p_hal);
+			/* treated as charger in. */
+			ret = USB_DET_DEVICE_CHARGER;
+			goto out2;
+
+		default:
+			MONITOR_ERR("into device confirm default, err!\n");
+			pStatus->device_confirm = 0;
+			ret = USB_DET_NONE;
+			goto out;
+		}
+	} else {	  
+		pStatus->device_confirm = 0;
+		pStatus->timer_steps =USB_DEVICE_DETECT_STEPS;
+		ret = USB_DET_NONE;
+		goto out;
+	}
+
+      out:
+	pStatus->timer_steps++;
+	if (pStatus->timer_steps > USB_DEVICE_DETECT_STEPS) {
+		pStatus->timer_steps = 0;
+	}
+      out2:
+	return ret;
+}
+
+/* 
+ * retval:
+ * refer to below macro:
+ *    USB_DET_HOST_NONE,
+ *    USB_DET_HOST_DEBOUNCING,
+ *    USB_DET_HOST_UDISK,
+ */
+static int usb_timer_det_udisk(umonitor_dev_status_t * pStatus)
+{
+	unsigned int val;
+	usb_hal_monitor_t *p_hal = &pStatus->umonitor_hal;
+
+	if (pStatus->timer_steps == 1) {
+
+		p_hal->set_dp_500k_15k(p_hal, 0, 1);	/* disable 500k, enable 15k. */
+
+		if (pStatus->vbus_enable_power == 0) {
+			p_hal->vbus_power_onoff(p_hal, 1);
+			pStatus->vbus_enable_power = 1;
+			p_hal->set_soft_id(p_hal, 1, 0);
+		}
+		goto out;
+	} else {
+		if (pStatus->vbus_enable_power != 1) {
+			USB_ERR_PLACE;
+		}
+		   
+		val = p_hal->get_linestates(p_hal);	// get dp dm status.
+		MONITOR_PRINTK("host debounce!!!, linestate %04x\n", val);
+		
+    pStatus->timer_steps = 0;
+    pStatus->host_confirm = 0;
+    return USB_DET_HOST_UDISK;
+		    
+		if ((val == 0x1) || (val == 0x2)) {
+			switch (pStatus->host_confirm) {
+			case 0:
+				pStatus->host_confirm = 1;
+				/* the last step is always debounce and confirm step. */
+				pStatus->timer_steps = USB_HOST_DETECT_STEPS;
+				pStatus->dp_dm_status = val;
+				return USB_DET_HOST_DEBOUNCING;
+
+			case 1:
+				if (val == pStatus->dp_dm_status) {
+					/* if enable monitor again, it should begin from step 0.  */
+					pStatus->timer_steps = 0;
+					pStatus->host_confirm = 0;
+					return USB_DET_HOST_UDISK;
+				} else {
+					pStatus->dp_dm_status = val;
+					pStatus->host_confirm = 0;
+					return USB_DET_HOST_DEBOUNCING;
+				}
+
+			default:
+				break;
+			}
+		} else {
+			pStatus->host_confirm = 0;
+			goto out;
+		}
+	}
+
+out:
+	pStatus->timer_steps++;
+	if (pStatus->timer_steps > USB_HOST_DETECT_STEPS) {
+		pStatus->timer_steps = 0;
+		return USB_DET_HOST_NONE;	/* nothing detect, maybe udisk is plug out. */
+	}
+	return USB_DET_HOST_DEBOUNCING;
+}
+
+/* 
+ * \B4\A6\C0\ED\BBָ\B4\B5\BDstep 0\A3\A8\BC\B4\B5\DA0\B2\BD\A3\A9\B5\C4\C7\E9\BF\F6\A1\A3step 0\BD׶β\BB\C7\F8\B7\D6device\BC\EC\B2⻹\CA\C7host\BC\EC\B2⣬
+ * \CB\FCֻ\CAǻָ\B4\B5\BDһ\B8\F6Ĭ\C8\CF״̬\A3\ACΪ\CF\C2һ\B4\CEdevice\BB\F2host\BC\EC\B2\E2\D7\F6׼\B1\B8\A1\A3 
+ */
+static int usb_timer_process_step0(umonitor_dev_status_t * pStatus)
+{
+	int ret = 0;
+	unsigned int status = 0;
+	usb_hal_monitor_t *p_hal = &pStatus->umonitor_hal;
+	
+	MONITOR_PRINTK("entring usb_timer_process_step0\n");
+
+	if ((pStatus->message_status & (0x1 << MONITOR_B_IN)) != 0) {
+		MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+		printk("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+		pStatus->core_ops->putt_msg(MON_MSG_USB_B_OUT);
+		pStatus->message_status =pStatus->message_status & (~(0x1 << MONITOR_B_IN));
+	}
+
+	if ((pStatus->message_status & (0x1 << MONITOR_A_IN)) != 0) {
+		MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_A_OUT\n", __FILE__, __LINE__);
+		printk("\n%s--%d, SYS_MSG_USB_A_OUT\n", __FILE__, __LINE__);
+		pStatus->core_ops->putt_msg(MON_MSG_USB_A_OUT);
+		pStatus->message_status = pStatus->message_status & (~(0x1 << MONITOR_A_IN));
+	}
+
+	/*
+	 * \B6\D4\D3\DA\D3\D0id pin, \BB\F2\D3\C3gpio\BC\EC\B2\E2idpin\B5\C4\C7\E9\BF\F6, \B5\B1idpinΪ0, \D4\F2\C8\C3\CB\FCһֱ\B4\A6\D3\DAhost\BC\EC\B2\E2״̬,
+	 * \B2\BBҪ\C8\C3vbus\B5\F4\B5\E7. һֱvbus\B9\A9\B5\E7,\BF\C9\D2Լ\E6\C8ݲ\E5\C8\EBmp3,mp4\B5\C4\C7\E9\BF\F6. (\D2\F2Ϊ\D5\E2Щ\C9豸\D3п\C9\C4\DC\D4ڹ\A9\B5\E7
+	 * \BC\B8ʮ\C3\EB\BA\F3dp\B2\C5\C9\CF\C0\AD\A1\A3
+	 */
+	if (p_hal->config->detect_type == UMONITOR_DEVICE_ONLY) {
+		ret = USB_ID_STATE_DEVICE;
+	} else if (p_hal->config->detect_type == UMONITOR_HOST_ONLY) {
+		ret = USB_ID_STATE_HOST;
+	} else {
+		ret = p_hal->get_idpin_state(p_hal);
+	}
+  MONITOR_PRINTK("idpin is %d\n", ret);
+  
+
+	if (ret != USB_ID_STATE_INVALID) {
+		if (ret == USB_ID_STATE_HOST) {
+host_detect:		  
+		  MONITOR_PRINTK("host detecting!!!!\n");
+			if ((pStatus->message_status & (0x1 << MONITOR_B_IN)) != 0) {
+				MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+				printk("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+				pStatus->core_ops->putt_msg(MON_MSG_USB_B_OUT);
+				pStatus->message_status =pStatus->message_status & (~(0x1 << MONITOR_B_IN));
+			}
+			if ((pStatus->message_status & (0x1 << MONITOR_CHARGER_IN)) != 0) {
+				MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_CHARGER_OUT\n", __FILE__, __LINE__);
+				pStatus->core_ops->putt_msg(MON_MSG_USB_CHARGER_OUT);
+				pStatus->message_status =pStatus->message_status & (~(0x1 << MONITOR_CHARGER_IN));
+			}
+      
+			p_hal->set_dp_500k_15k(p_hal, 0, 1);	/* disable 500k, enable 15k. */
+
+			if (pStatus->vbus_enable_power == 0) {
+				p_hal->vbus_power_onoff(p_hal, 1);
+				pStatus->vbus_enable_power = 1;
+				p_hal->set_soft_id(p_hal, 1, 0);
+			}
+			pStatus->det_phase = 1;
+		} else {
+		  MONITOR_PRINTK("device detect prepare!!!!\n");
+			if ((pStatus->message_status & (0x1 << MONITOR_A_IN)) != 0) {
+				MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_A_OUT\n", __FILE__, __LINE__);
+				printk("\n%s--%d, SYS_MSG_USB_A_OUT\n", __FILE__, __LINE__);
+				pStatus->core_ops->putt_msg(MON_MSG_USB_A_OUT);
+				pStatus->message_status = pStatus->message_status & (~(0x1 << MONITOR_A_IN));
+			}			
+			if (pStatus->vbus_enable_power) {
+			    p_hal->vbus_power_onoff(p_hal, 0);
+			    pStatus->vbus_enable_power = 0;
+			}
+			p_hal->set_dp_500k_15k(p_hal, 0, 0);	/* disable 500k, disable 15k. */
+			p_hal->set_soft_id(p_hal, 1, 1);
+
+			pStatus->det_phase = 0;
+		}
+		pStatus->device_confirm = 0;
+		pStatus->host_confirm = 0;
+		pStatus->timer_steps = 1;
+		goto out;
+	}
+
+	/* the last time check host state before change to device detect phase. */
+	if ((pStatus->vbus_enable_power != 0) && (pStatus->det_phase != 0)) {
+		pStatus->dp_dm_status = p_hal->get_linestates(p_hal);	// get dp dm status.
+		if ((pStatus->dp_dm_status == 0x1) || (pStatus->dp_dm_status == 0x2)) {
+			pStatus->timer_steps = USB_HOST_DETECT_STEPS;
+			pStatus->host_confirm = 0;
+			goto out;
+		}
+	}
+
+	p_hal->vbus_power_onoff(p_hal, 0);
+	pStatus->vbus_enable_power = 0;
+	p_hal->set_dp_500k_15k(p_hal, 0, 0);	/* disable 500k, disable 15k. */
+	p_hal->set_soft_id(p_hal, 1, 1);
+	
+	pStatus->check_cnt++;
+
+	/* if it's the first time to check, must in checking device phase. */
+	if ((pStatus->check_cnt == 1) ||
+	    (pStatus->port_config->detect_type == UMONITOR_DEVICE_ONLY)) {
+		pStatus->det_phase = 0;
+	} else {
+		/* reverse detect phase. */
+		pStatus->det_phase = !pStatus->det_phase;
+
+		/* if it's B_IN status, it needn't to check host in, because there is just one usb port. 
+		   ͬʱ\A3\AC\C8\E7\B9\FBֻ\C1\AC\BD\D3usb\B3\E4\B5\E7\C6\F7\A3\AC\B4\CBʱ\D4\D9ʹ\D3\C3GPIO\B6\D4\CD⹩\B5\E7\C0\B4\BC\EC\B2\E9host\CAǷ\F1\B2\E5\C8룬\D4\F2\BBᵼ\D6»\FA\C6\F7\B5\F4\B5硣
+		   һ\D1\F9Ҳ\CA\C7\D0\E8Ҫ\B4\CBʱ\BD\FBֹ\BC\EC\B2\E2host */
+		status = pStatus->message_status & ((0x1 << MONITOR_B_IN) | (0x1 << MONITOR_CHARGER_IN));
+		if ((pStatus->det_phase == 1) && (status != 0)) {
+			pStatus->det_phase = 0;
+			goto out1;
+		}
+		pStatus->check_cnt = 0;
+		goto host_detect;
+		
+	}
+out1:
+	pStatus->device_confirm = 0;
+	pStatus->host_confirm = 0;
+	pStatus->timer_steps = 1;
+
+out:
+	return 0;
+}
+
+/******************************************************************************/
+/*!
+* \brief  check whether usb plug in/out
+*
+* \par    Description
+*         this function is a timer func, interval is 500ms.
+*
+* \param[in]  null
+* \return     null
+* \ingroup   usbmonitor
+*
+* \par
+******************************************************************************/
+void umonitor_timer_func(void)
+{
+	int ret = 0;
+	unsigned int status = 0;
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t * p_hal;
+	u32 reg;
+    
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;
+	
+	MONITOR_PRINTK("entring umonitor_timer_func\n");
+
+	if ((pStatus->port_config->detect_type == UMONITOR_DISABLE)
+		|| (pStatus->detect_valid == 0)) {
+		goto out;
+	}
+	pStatus->detect_running = 1;
+
+	/* err check! */
+	if ((pStatus->timer_steps > USB_DEVICE_DETECT_STEPS)
+	    && (pStatus->timer_steps > USB_HOST_DETECT_STEPS)) {
+		MONITOR_ERR("timer_steps err:%d \n", pStatus->timer_steps);
+		pStatus->timer_steps = 0;
+		goto out;
+	}
+	//usb_monitor_debug_status_inf(usb_ctrl_no);
+
+	if (pStatus->timer_steps == 0) {	/* power on/off phase. */
+		usb_timer_process_step0(pStatus);
+		goto out;
+	}
+
+	if (pStatus->det_phase == 0) {	/* power off, device detect phase. */
+		ret = usb_timer_det_pc_charger(pStatus);
+		switch (ret) {
+		case USB_DET_NONE:
+			if ((pStatus->message_status & (0x1 << MONITOR_B_IN)) != 0) {
+				//MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+				printk("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+				pStatus->core_ops->putt_msg(MON_MSG_USB_B_OUT);
+				pStatus->message_status =pStatus->message_status & (~(0x1 << MONITOR_B_IN));
+			}
+			if ((pStatus->message_status & (0x1 << MONITOR_CHARGER_IN)) != 0) {
+				printk("\n%s--%d, SYS_MSG_USB_CHARGER_OUT\n", __FILE__, __LINE__);
+				//MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_CHARGER_OUT\n", __FILE__, __LINE__);
+				pStatus->core_ops->putt_msg(MON_MSG_USB_CHARGER_OUT);
+				pStatus->message_status = pStatus->message_status & (~(0x1 << MONITOR_CHARGER_IN));
+			}
+			break;
+
+		case USB_DET_DEVICE_DEBUOUNCING:	/* debounce. */
+			break;
+
+		case USB_DET_DEVICE_PC:
+			if(p_hal->get_idpin_state(p_hal) != USB_ID_STATE_DEVICE){
+				pStatus->device_confirm = 0;
+				pStatus->timer_steps =0;
+                		goto out;
+			}
+			status = pStatus->message_status & (0x1 << MONITOR_B_IN);
+			if (status != 0) {
+				goto out;
+			}
+			p_hal->set_mode(p_hal, USB_IN_DEVICE_MOD);
+			//need to reset dp/dm before dwc3 loading
+			reg = readl(p_hal->usbecs);
+			reg &=  ~((0x1 << USB3_P0_CTL_DPPUEN_P0)|(0x1 << USB3_P0_CTL_DMPUEN_P0)); 
+			writel(reg, p_hal->usbecs );
+			//MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_B_IN\n", __FILE__, __LINE__);
+			printk("\n%s--%d, SYS_MSG_USB_B_IN\n", __FILE__, __LINE__);
+			pStatus->core_ops->putt_msg(MON_MSG_USB_B_IN);
+			pStatus->message_status |= 0x1 << MONITOR_B_IN;
+			pStatus->detect_valid = 0;	//disable detection
+			goto out;	/* todo stop timer. */
+
+		case USB_DET_DEVICE_CHARGER:
+			/* if B_IN message not clear, clear it. B_OUT when adaptor is in. */
+			status = pStatus->message_status & (0x1 << MONITOR_B_IN);
+			if (status != 0) {
+			  printk("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+				//MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_B_OUT\n", __FILE__, __LINE__);
+				pStatus->core_ops->putt_msg(MON_MSG_USB_B_OUT);
+				pStatus->message_status =pStatus->message_status & (~(0x1 << MONITOR_B_IN));
+			}
+			/* if adaptor in is send, it needn't sent again. */
+			status = pStatus->message_status & (0x1 << MONITOR_CHARGER_IN);
+			if (status != 0) {
+				goto out;
+			}
+			p_hal->set_mode(p_hal, USB_IN_DEVICE_MOD);
+			MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_CHARGER_IN\n", __FILE__, __LINE__);
+			pStatus->core_ops->putt_msg(MON_MSG_USB_CHARGER_IN);
+			pStatus->message_status |= 0x1 << MONITOR_CHARGER_IN;
+			pStatus->detect_valid = 0;	//disable detection
+			goto out;	/* todo stop timer. */
+
+		default:
+			USB_ERR_PLACE;
+			break;
+		}
+		goto out;
+	} else {		/* power on, host detect phase. */
+
+		ret = usb_timer_det_udisk(pStatus);
+		status = pStatus->message_status & (0x1 << MONITOR_A_IN);
+		if ((status != 0) && (ret == USB_DET_HOST_NONE)) {
+			//MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_A_OUT\n", __FILE__, __LINE__);
+			printk("\n%s--%d, SYS_MSG_USB_A_OUT\n", __FILE__, __LINE__);
+			pStatus->core_ops->putt_msg(MON_MSG_USB_A_OUT);
+			pStatus->message_status = pStatus->message_status & (~(0x1 << MONITOR_A_IN));
+			goto out;
+		}
+		if (ret == USB_DET_HOST_UDISK) {
+			p_hal->set_mode(p_hal, USB_IN_HOST_MOD);
+			//MONITOR_PRINTK("\n%s--%d, SYS_MSG_USB_A_IN\n", __FILE__, __LINE__);
+			printk("\n%s--%d, SYS_MSG_USB_A_IN\n", __FILE__, __LINE__);
+			pStatus->core_ops->putt_msg(MON_MSG_USB_A_IN);
+			pStatus->message_status |= 0x1 << MONITOR_A_IN;
+
+			/*\C8\E7\B9\FB\CA\C7A\CF߲\E5\C8룬\D4\F2\B9رն\A8ʱ\C6\F7\A3\BBB\CF߲\E5\C8룬\B6\A8ʱ\C6\F7\B2\BB\D3ùر\D5 */
+			pStatus->detect_valid = 0;	//disable detection
+			goto out;	/* todo stop timer. */
+		}
+		goto out;
+	}
+	
+out:
+	pStatus->detect_running = 0;
+	return;
+}
+
+/******************************************************************************/
+/*!
+* \brief  set monitor detect flag
+*
+* \par    Description
+*         set monitor detect flag
+*
+* \param[in]  status
+*             1---   set detection flag to detect
+*             0---   reverse
+* \return     0------\C9\E8\D6óɹ\A6
+* \ingroup   usbmonitor
+*
+* \par
+******************************************************************************/
+static int set_monitor_detect_flag(umonitor_dev_status_t *pStatus, unsigned int status)
+{
+	int i;
+	unsigned int ms_status = 0;	/* record is a in ? */
+	usb_hal_monitor_t *p_hal = &pStatus->umonitor_hal;
+
+	pStatus->check_cnt = 0;
+	pStatus->det_phase = 0;
+	pStatus->timer_steps = 0;
+
+	if (status != 0) {	/*enable detect flag */
+		p_hal->vbus_power_onoff(p_hal, 0);
+		pStatus->vbus_enable_power = 0;
+
+		if (pStatus->detect_valid == 0) {
+			MONITOR_PRINTK("%s,%d\n", __FUNCTION__, __LINE__);
+			pStatus->detect_valid = 1;
+			goto out;
+		} else {
+			MONITOR_PRINTK("usb detection flag is already setted, %s,%d\n", __FUNCTION__, __LINE__);
+		}
+	} 
+	else {		/*disable detection flag */
+		i = 0;
+		do {
+			if (pStatus->detect_running == 0) {
+				pStatus->detect_valid = 0;
+				break;
+			}
+			msleep(1);
+			++i;
+		} while (i < 1000);
+		MONITOR_PRINTK("enable detection flag\n");
+		
+		if (ms_status == 0) {
+			/* make sure power is off. */
+			p_hal->vbus_power_onoff(p_hal, 0);
+			pStatus->vbus_enable_power = 0;
+			p_hal->set_soft_id(p_hal, 1, 1);
+		}
+	}
+
+out:
+	if (pStatus->core_ops->wakeup_func != NULL) {
+		pStatus->core_ops->wakeup_func();
+	}
+	return 0;
+}
+
+/*! \cond USBMONITOR_INTERNAL_API*/
+/******************************************************************************/
+/*!
+* \brief  enable or disable usb plug_in/out check
+*
+* \par    Description
+*         enable or disable the func of checking usb plug_in/out
+*
+*
+* \param[in]  status
+*             1---   enable check func;
+*             0---   disable check func;
+* \return     0------ʹ\C4\DC/\BD\FBֹ\B3ɹ\A6
+                \B8\BAֵ---\C7\FD\B6\AF\B5\B1ǰæ\A3\AC\C7\EB\C9Ժ\F2\D6\D8\D0½\F8\D0д˲\D9\D7\F7
+* \ingroup   usbmonitor
+*
+* \par
+******************************************************************************/
+int umonitor_detection(unsigned int status)
+{
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t * p_hal;
+
+
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;
+	MONITOR_PRINTK("umonitor_detection:%d\n", status);
+
+	if (status != 0) {
+		p_hal->dwc3_otg_mode_cfg(p_hal);
+		p_hal->aotg_enable(p_hal, 1);
+		p_hal->set_mode(p_hal, USB_IN_DEVICE_MOD);
+		set_monitor_detect_flag(pStatus, 1);
+	} else {
+		//\D5ⲿ\B7\D6\CF\D6\D4\DA\D2\D1\CE\DEЧ,\D3\C9\D4\DA\D2Ѿ\AD\BC\EC\B2⵽B\BB\F2\D5\DFA\B2\E5\C8\EBʱ,\B7\A2\CB\CD\C1\CB\CF\FBϢ\BA\F3,\BD\AB\B6\A8ʱ\C6\F7port_timerֹͣ;
+		//checktimer\C8Ծ\C9\D4\CB\D0м\E0\B2\E2A(id\CAǷ\F1\B1仯)\BB\F2\D5\DFB(vbus\CAǷ\F1\B8ı\E4)\B2\E5\C8\EB\B5\C4״̬\CAǷ\F1\B7\A2\C9\FA\B8ı\E4.
+		//\B4˴\A6Ϊ\B1\A3\C1\F4ԭʼ\B4\FA\C2\EB,/*disable detection,\BC\D3\D4\D8UDC\C7\FD\B6\AFʱ\A3\AC\CFȹرն\A8ʱ\C6\F7\BC\EC\B2\E2 */
+		p_hal->aotg_enable(p_hal, 0);
+		set_monitor_detect_flag(pStatus, 0);
+	}
+	return 0;
+}
+
+/*! \cond NOT_INCLUDE*/
+/******************************************************************************/
+/*!
+* \brief  parse the runtime args of monitor driver.
+* \par    Description
+*         \B3\F5ʼ\BB\AF\A3\AC\BF\AAʼ׼\B1\B8\BD\F8\D0м\EC\B2⡣
+*
+* \retval      0---args parse successed
+* \ingroup     UsbMonitor
+******************************************************************************/
+int umonitor_core_init(umonitor_api_ops_t * core_ops,
+		   umon_port_config_t * port_config , unsigned int base)
+{
+	umonitor_dev_status_t *pStatus;
+
+	pStatus = kmalloc(sizeof (umonitor_dev_status_t), GFP_KERNEL);
+	if (pStatus == NULL) {
+		return -1;
+	}
+	umonitor_status = pStatus;
+
+	usb_hal_init_monitor_hw_ops(&pStatus->umonitor_hal, port_config, base);
+	usb_init_monitor_status(pStatus);
+	pStatus->core_ops = core_ops;
+	pStatus->port_config = port_config;
+
+	return 0;
+}
+
+int umonitor_core_exit(void)
+{
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t *p_hal;
+
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;
+
+	p_hal->enable_irq(p_hal, 0);
+	if (pStatus != NULL)
+		kfree(pStatus);
+		
+	umonitor_status = NULL;
+	return 0;
+}
+
+unsigned int umonitor_get_run_status(void)
+{
+	umonitor_dev_status_t *pStatus;
+
+	pStatus = umonitor_status;
+	
+	return (unsigned int)pStatus->detect_valid;
+}
+
+unsigned int umonitor_get_message_status(void)
+{
+	umonitor_dev_status_t *pStatus;
+
+	pStatus = umonitor_status;
+	
+	return (unsigned int)pStatus->message_status;
+}
+
+void umonitor_printf_debuginfo(void)
+{
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t *p_hal;
+
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;
+
+	usb_monitor_debug_status_inf();
+	printk("in printf_debuginfo\n");
+	p_hal->debug(p_hal);
+
+	return;
+}
+
+int umonitor_vbus_power_onoff(int value)
+{
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t *p_hal;
+
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;
+	
+	return p_hal->vbus_power_onoff(p_hal, value);
+}
+
+int umonitor_core_suspend(void)
+{
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t *p_hal;
+
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;
+
+  pStatus->detect_valid = 0;
+  
+  printk("SUSPEND pStatus->message_status is %d!!!!!!!!!!!!!!\n", pStatus->message_status);
+  
+	if(pStatus->vbus_enable_power && p_hal->vbus_power_onoff)
+		p_hal->vbus_power_onoff(p_hal,  0);
+	
+  p_hal->suspend_or_resume(p_hal, 1);
+	
+	return 0;
+}
+
+int umonitor_core_resume(void)
+{
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t *p_hal;
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;	
+	
+	printk(KERN_DEBUG"RESUME pStatus->message_status is %d!!!!!!!!!!!!!!\n", pStatus->message_status);
+
+	if((pStatus->message_status &(0x1 << MONITOR_B_IN)) != 0){
+		printk(KERN_DEBUG"RESUME SNED B_OUT\n");
+		pStatus->core_ops->putt_msg(MON_MSG_USB_B_OUT);
+			pStatus->message_status &= ~(0x1 << MONITOR_B_IN);
+	}
+	if((pStatus->message_status &(0x1 << MONITOR_A_IN)) != 0){
+		printk(KERN_DEBUG"RESUME SNED A_OUT\n");
+		//p_hal->vbus_power_onoff(p_hal,  1);
+		//pStatus->vbus_enable_power = 1;
+		pStatus->core_ops->putt_msg(MON_MSG_USB_A_OUT);
+		pStatus->message_status &= ~(0x1 << MONITOR_A_IN);
+	}
+	p_hal->suspend_or_resume(p_hal, 0);
+	umonitor_detection(1);
+	return 0;
+}
+
+/*\B1\A3֤\B9ػ\FA\C1\F7\B3\CC\D6вŻ\E1\B5\F7\D3\C3,\C6\E4\CB\FC\B5ط\BD\B2\BB\BB\E1\B5\F7\D3\C3*/
+int umonitor_dwc_otg_init(void)
+{
+	umonitor_dev_status_t *pStatus;
+	usb_hal_monitor_t *p_hal;
+
+	pStatus = umonitor_status;
+	p_hal = &pStatus->umonitor_hal;
+
+  p_hal->dwc3_otg_init(p_hal);
+	
+	return 0;
+}
diff --git a/drivers/usb/monitor/umonitor_core.h b/drivers/usb/monitor/umonitor_core.h
new file mode 100644
index 0000000..3f7643e
--- /dev/null
+++ b/drivers/usb/monitor/umonitor_core.h
@@ -0,0 +1,130 @@
+/*! \cond USBMONITOR*/
+/*********************************************************************************
+*                            Module: usb monitor driver
+*                (c) Copyright 2003 - 2008, Actions Co,Ld. 
+*                        All Right Reserved 
+*
+* History:        
+*      <author>      <time>       <version >    <desc>
+*       houjingkun   2011/07/08   1.0         build this file 
+********************************************************************************/ 
+/*!
+ * \file   umonitor_core.h
+ * \brief  
+ *      usb monitor detect opration headfile.
+ * \author houjingkun
+ * \par GENERAL DESCRIPTION:
+ * \par EXTERNALIZED FUNCTIONS:
+ *       null
+ *
+ *  Copyright(c) 2008-2012 Actions Semiconductor, All Rights Reserved.
+ *
+ * \version 1.0
+ * \date  2011/07/08
+ *******************************************************************************/
+#ifndef _UMONITOR_CORE_H_
+#define _UMONITOR_CORE_H_
+
+#include  "umonitor_hal.h"
+
+#define USB_ERR_PLACE               printk("err:%s,%d\n", __FILE__, __LINE__)
+
+typedef struct umonitor_api_ops {
+	/* wakeup_func -- wakeup usb monitor detect thread. */
+	void (* wakeup_func) (void);
+
+	#define MON_MSG_USB_B_IN		1
+	#define MON_MSG_USB_B_OUT		2
+	#define MON_MSG_USB_A_IN		3
+	#define MON_MSG_USB_A_OUT		4
+	#define MON_MSG_USB_CHARGER_IN		5
+	#define MON_MSG_USB_CHARGER_OUT		6
+	void (* putt_msg)(unsigned int msg); 
+} umonitor_api_ops_t;
+
+
+
+typedef struct umonitor_dev_status {
+	usb_hal_monitor_t umonitor_hal;
+
+	/* detect valid or not. 1--valid, 0--invalid. */
+	volatile unsigned char detect_valid;
+	/* 1--usb monitor is detecting, 0--not in detecting state. */
+	volatile unsigned char detect_running;
+
+	volatile unsigned char vbus_status;	/* detect vbus status. 1-- valid. */
+	volatile unsigned char dc5v_status;	/* detect dc5v status. 1-- valid. */
+	volatile unsigned char vbus_enable_power;	/* 1-- valid. */
+	volatile unsigned char det_phase;	/* 0--device detecting, 1--host detecting. */
+	/*
+	 * confirm device state. 0--not detect, 1--vbus on detected, enable 500k, 
+	 * 2--dp dm detect, 3-- dp dm debounce.
+	 */
+	volatile unsigned char device_confirm;
+
+#define MAX_DETECT_SOF_CNT  50
+	volatile unsigned char sof_check_times;
+
+	/*
+	 * confirm host state. 0--not detect, 1--dp,dm detected, 
+	 * 2--dp dm debounce.
+	 */
+	volatile unsigned char host_confirm;
+	volatile unsigned char usb_pll_on;	/* 1--on, 0--off. */
+	/*
+	 * 0 ~ 3 bit - detect device or host. refer to DET_USB_MODE_T. 
+	 * 4 ~ 7 bit - vbus detect mode. refer to DET_VBUS_MODE_T.
+	 * 8 ~ 11 bit - id detect mode. refer to DET_ID_MODE_T.
+	 * 12 ~ 15 bit - dc5v detect mode. refer to DET_DC5V_MODE_T.
+	 */
+	volatile unsigned int detect_mode;
+	volatile unsigned char reserv[2];
+	volatile unsigned int dp_dm_status;	/* 00 or 11, connet to pc or charger; 01 or 10, connet with udisk. */
+	/* 
+	 * detect steps. device steps: USB_DEVICE_DETECT_STEPS 
+	 * host steps: USB_HOST_DETECT_STEPS
+	 */
+	volatile int timer_steps;
+	volatile unsigned int timer_interval;	/* msecond. */
+	volatile int check_cnt;	/* total detect count. */
+
+	/* message status that indicate what message has been send. */
+#define MONITOR_B_IN            0
+#define MONITOR_CHARGER_IN      1
+#define MONITOR_A_IN            2
+	volatile unsigned int message_status;
+	//volatile unsigned int fix_bug_record; 
+
+	umonitor_api_ops_t *core_ops;
+	umon_port_config_t *port_config;
+} umonitor_dev_status_t;
+
+int umonitor_core_init(umonitor_api_ops_t *core_ops, umon_port_config_t *port_config, unsigned int base);
+
+int umonitor_core_exit(void);
+
+/* status: 1--enable detecting, 0--disable detecting. */
+int umonitor_detection(unsigned int status);
+
+/* this function is a timer func. */
+void umonitor_timer_func(void);
+
+/* \BB\F1ȡ\D4\CB\D0е\BD\CF\C2һ\B4μ\EC\B2\E2\B5\C4ʱ\BC\E4\BC\E4\B8\F4\A3\AC\B7\B5\BB\D8ֵ\D2Ժ\C1\C3\EBΪ\B5\A5λ\A1\A3 */
+unsigned int umonitor_get_timer_step_interval(void);
+
+unsigned int umonitor_get_run_status(void);
+
+unsigned int umonitor_get_message_status(void);
+
+void umonitor_printf_debuginfo(void);
+
+int umonitor_vbus_power_onoff(int value);
+
+int umonitor_core_suspend(void);
+
+int umonitor_core_resume(void);
+
+int umonitor_dwc_otg_init(void);
+#endif  /* _UMONITOR_CORE_H_ */
+/*! \endcond*/
+
diff --git a/drivers/usb/monitor/umonitor_hal.c b/drivers/usb/monitor/umonitor_hal.c
new file mode 100644
index 0000000..9f9aa3d
--- /dev/null
+++ b/drivers/usb/monitor/umonitor_hal.c
@@ -0,0 +1,534 @@
+/*********************************************************************************
+*                            Module: usb monitor driver
+*                (c) Copyright 2003 - 2008, Actions Co,Ld. 
+*                        All Right Reserved 
+*
+* History:        
+*      <author>      <time>       <version >    <desc>
+*       houjingkun   2011/07/08   1.0         build this file 
+********************************************************************************/
+
+/*!
+ * \file   umonitor_hal.c
+ * \brief  
+ *      usb monitor hardware opration api code.
+ * \author houjingkun
+ * \par GENERAL DESCRIPTION:
+ * \par EXTERNALIZED FUNCTIONS:
+ *       null
+ *
+ *  Copyright(c) 2008-2012 Actions Semiconductor, All Rights Reserved.
+ *
+ * \version 1.0
+ * \date  2011/07/08
+ *******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/atc260x/atc260x.h>
+#include <mach/hardware.h>
+
+#include "aotg_regs.h"
+#include "umonitor_hal.h"
+
+#define USB_PLUGED_PC	    1
+#define USB_PLUGED_ADP		2
+
+
+static void dwc3_controllor_exit(usb_hal_monitor_t * pdev);
+void __dwc3_controllor_mode_cfg(usb_hal_monitor_t *pdev);
+
+extern int atc260x_enable_vbusotg(int on);
+
+
+void mon_dwc3_set_mode(usb_hal_monitor_t * pdev, int mode)
+{
+	u32 reg;
+
+	reg = readl(pdev->io_base + DWC3_GCTL);
+	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
+	reg |= DWC3_GCTL_PRTCAPDIR(mode);
+	writel(reg, pdev->io_base + DWC3_GCTL);
+}
+
+
+static int usb_monitor_vbus_power(usb_hal_monitor_t * pdev, int is_on)
+{
+ 	 MONITOR_PRINTK("usb_monitor_vbus_power %04x\n", is_on);
+	if(is_on){
+		atc260x_enable_vbusotg(is_on);
+        	if(pdev->config->power_switch_gpio_no !=0xffff)
+			gpio_set_value_cansleep(pdev->config->power_switch_gpio_no, pdev->config->power_switch_active_level);
+	}else{
+		if(pdev->config->power_switch_gpio_no !=0xffff)
+			gpio_set_value_cansleep(pdev->config->power_switch_gpio_no, !pdev->config->power_switch_active_level);
+		atc260x_enable_vbusotg(is_on);
+	}	
+	
+	return 0;
+}
+
+static int usb_get_dc5v_state(usb_hal_monitor_t * pdev)
+{
+	/* no use. */
+	return USB_DC5V_INVALID;
+}
+
+static int get_usb_plug_type(struct usb_hal_monitor *pdev)
+{
+	int ret = 0;
+	int reg_bk;
+	int reg;
+
+	reg_bk = readl(pdev->usbecs);
+	if ((reg_bk & (1 << 11))) {
+		reg = reg_bk;
+		writel(reg | 0x0000f000, pdev->usbecs);	 /* dp up enable, dp down disable */
+		udelay(200);
+		reg = readl(pdev->usbecs);
+		if((reg & 0x00000018) != 0) {			/* bit 3, bit 4 not 0, this is usb_adapter */
+			//printf("----- current connect is USB_ADPT! \n");
+			ret = USB_PLUGED_ADP;
+		} else {
+			//printf("----- current connect is USB_PC! \n");
+			ret = USB_PLUGED_PC;
+		}
+		writel(reg_bk, pdev->usbecs);			/*restore the USB3_P0_CTL */
+	}
+	
+	return ret;
+}
+
+static int usb_get_vbus_state(usb_hal_monitor_t * pdev)
+{
+	int ret = USB_VBUS_INVALID;
+	s32 adc_val;
+
+	switch (pdev->config->vbus_type) {
+   	case UMONITOR_USB_VBUS:
+		/* vbus valid. */
+		  ret = readl(pdev->usbecs) & (1 << USB3_P0_CTL_VBUS_P0);
+		  ret = ret ? USB_VBUS_HIGH: USB_VBUS_LOW;
+		  break;
+   	case UMONITOR_GPIO_VBUS:
+   	  break;
+   	case UMONITOR_DC5V_VBUS:
+    	  ret = atc260x_ex_auxadc_read_by_name("VBUSV", &adc_val);
+    	  if(ret < 0)
+			break;
+		  ret = (adc_val > VBUS_THRESHOLD) ? USB_VBUS_HIGH: USB_VBUS_LOW;
+		  break;
+	  default:
+		  break;
+	}
+	/*for debug only:let user can detect host/device as wish*/
+	if((pdev->config->vbus_debug ==0)||(pdev->config->vbus_debug ==1))
+		return pdev->config->vbus_debug;
+    	/* printk vbus state for debug*/
+	if(pdev->config->vbus_debug == 2)
+		printk("\n  usb_get_vbus_state: %d \n",ret);
+    
+	MONITOR_PRINTK("%s state: %u\n", __func__, ret);
+	return ret;	
+}
+
+static int usb_hardware_init(usb_hal_monitor_t * pdev);
+static int usb_get_idpin_state(usb_hal_monitor_t * pdev)
+{
+	int value,ret = USB_ID_STATE_INVALID;  
+    
+	value = readl(pdev->usbpll) & 0x1f;
+	if(value == 0){
+	       //need to open usbpll before read idpin status
+		__dwc3_controllor_mode_cfg(pdev);
+       }
+    
+	switch (pdev->config->idpin_type) {
+	case UMONITOR_USB_IDPIN:
+    ret = (readl(pdev->usbecs) &
+         (1 << USB3_P0_CTL_ID_P0)) ? USB_ID_STATE_DEVICE:USB_ID_STATE_HOST;
+		break;
+	case UMONITOR_SOFT_IDPIN:
+        	break;
+	case UMONITOR_GPIO_IDPIN:
+		if(0==gpio_get_value_cansleep(pdev->config->idpin_gpio_no))
+			ret=USB_ID_STATE_HOST;
+		else
+			ret = USB_ID_STATE_DEVICE;
+         break;
+	default:
+		break;
+	}
+	if(value == 0){
+	    	//need to close usbpll after read idpin status
+	      	dwc3_controllor_exit( pdev);
+	}
+	/*for debug only:let user can detect host/device as wish*/
+	if((pdev->config->idpin_debug ==0)||(pdev->config->idpin_debug ==1))
+		return (pdev->config->idpin_debug?USB_ID_STATE_DEVICE: USB_ID_STATE_HOST);
+	/* printk idpin state for debug*/    
+    	if(pdev->config->idpin_debug ==2)
+		printk("\n  usb_get_idpin_state: %s \n",(ret==1)?"device":"host");            
+	return ret;
+}
+
+static unsigned int usb_get_linestates(usb_hal_monitor_t * pdev)
+{
+	unsigned int ls;
+
+	ls = ((readl(pdev->usbecs) & USB3_P0_CTL_LS_P0_MASK) >> USB3_P0_CTL_LS_P0_SHIFT);
+	return ls;
+}
+
+static int usb_set_dp_500k_15k(usb_hal_monitor_t * pdev, int enable_500k_up,
+			       int enable_15k_down)
+{
+	unsigned int val;
+	
+	val = readl(pdev->usbecs) & (~((1 << USB3_P0_CTL_DPPUEN_P0) |
+			(1 << USB3_P0_CTL_DMPUEN_P0) |
+			(1 << USB3_P0_CTL_DPPDDIS_P0) |
+			(1 << USB3_P0_CTL_DMPDDIS_P0)));
+			
+	if (enable_500k_up != 0) {
+		val |= (1 << USB3_P0_CTL_DPPUEN_P0)|(1 << USB3_P0_CTL_DMPUEN_P0);
+	}
+	if (enable_15k_down == 0) {
+		val |= (1 << USB3_P0_CTL_DPPDDIS_P0)|(1 << USB3_P0_CTL_DMPDDIS_P0);
+	}
+	
+	MONITOR_PRINTK("dpdm is %08x\n", val);
+	writel(val, pdev->usbecs);	/* 500k up enable, 15k down disable; */
+	return 0;	
+	
+}
+
+static int usb_set_soft_id(usb_hal_monitor_t * pdev, int en_softid,
+			   int id_state)
+{
+#if 0 //no soft idpin in ATM7059
+	unsigned int val;
+
+	if (pdev->config->idpin_type == UMONITOR_USB_IDPIN) {
+		/* ignore soft idpin setting. */
+		en_softid = 0;
+	}
+	val = readl(pdev->usbecs);
+	if (en_softid != 0) {
+		val |= 0x1 << USB3_P0_CTL_SOFTIDEN_P0;	/* soft id enable. */
+	} else {
+		val &= ~(0x1 << USB3_P0_CTL_SOFTIDEN_P0);	/* soft id disable. */
+	}
+
+	if (id_state != 0) {
+		val |= (0x1 << USB3_P0_CTL_SOFTID_P0);
+	} else {
+		val &= ~(0x1 << USB3_P0_CTL_SOFTID_P0);
+	}
+	writel(val, pdev->usbecs);
+#endif    
+	return 0;	
+}
+
+static int usb_set_soft_vbus(usb_hal_monitor_t * pdev, int en_softvbus, int vbus_state)
+{
+	unsigned int val;
+
+	if (pdev->config->vbus_type == UMONITOR_USB_VBUS) {
+		/* ignore soft vbus setting. */
+		en_softvbus = 0;
+	}
+
+	val = readl(pdev->usbecs);
+	if (en_softvbus != 0) {
+		val |= 0x1 << USB3_P0_CTL_SOFTVBUSEN_P0;	/* soft id enable. */
+	} else {
+		val &= ~(0x1 << USB3_P0_CTL_SOFTVBUSEN_P0);	/* soft id disable. */
+	}
+
+	if (vbus_state != 0) {
+		val |= (0x1 << USB3_P0_CTL_SOFTVBUS_P0);
+	}else {
+		val &= ~(0x1 << USB3_P0_CTL_SOFTVBUS_P0);
+	}
+	writel(val, pdev->usbecs);
+	
+	return 0;
+}
+
+static void usb_hal_set_cmu_usbpll(usb_hal_monitor_t *pdev, int enable)
+{
+	if (enable != 0) {
+		writel(readl(pdev->usbpll) | (0x1f), pdev->usbpll);
+	} else {
+		writel(readl(pdev->usbpll) & ~(0x1f),pdev->usbpll);
+	}
+	mdelay(2);
+}
+
+/******************************************************************************/
+/*!
+ * \par  Description:
+ *       \B6\D4usbģ\BF\E9\BD\F8\D0г\F5ʼ\BB\AF\A3\A8\B0\FC\C0\A8\BF\AA\C6\F4ʱ\D6ӣ\AC\B8\B4λ\D5\FB\B8\F6usbӲ\BC\FEģ\BF飬\B2\A2ȷ\B1\A3\B8\B4λ\D4ڷ\B5\BB\D8ǰ\CD\EA\B3\C9
+ * \param[in] void
+ * \param[in] void
+ * \return    int
+ * \retval    0\A3\BAusbģ\BF\E9\B3\F5ʼ\BB\AF\CD\EA\B3\C9    \B8\BAֵ\A3\BAusbģ\BF\E9\B3\F5ʼ\BB\AFʧ\B0\DC
+ * \ingroup   hal_usb
+ * \par
+ * \note
+ * 
+ *******************************************************************************/
+static int usb_hardware_init(usb_hal_monitor_t * pdev)
+{  
+	//writel((readl(pdev->usbecs) | 0x0000f000), pdev->usbecs);	
+	//set VBUS detection threshold,VBUS_DET_THRESHOLD_LEVEL3
+	writel((readl(pdev->usbecs) | VBUS_DET_THRESHOLD_LEVEL3), pdev->usbecs);
+  
+  MONITOR_PRINTK("usbecs value is %08x------>/n", readl(pdev->usbecs));
+		
+	return 0;
+}
+
+/******************************************************************************/
+/*!                    
+* \par  Description:
+*     enable or disable the usb controller
+* \param[in]    aotg  contains the controller info
+* \param[in]    enable  enable(1) or disable(0) the controller  
+* \return       the result  
+* \retval           0 sucess 
+* \retval           1 failed
+* \ingroup      USB_UOC
+*******************************************************************************/
+static int usb_hal_aotg_enable(usb_hal_monitor_t * pdev, int enable)
+{
+	if (enable != 0) {
+		MONITOR_PRINTK("aotg mon enable\n");
+		if (usb_hardware_init(pdev) != 0) {
+			return -1;
+		}
+	} else {
+		MONITOR_PRINTK("aotg mon disable\n");		  
+	}
+	return 0;
+}
+
+static int usb_hal_set_mode(usb_hal_monitor_t * pdev, int mode)
+{
+	if (mode == USB_IN_DEVICE_MOD) {
+		//writel(readl(pdev->usbecs) | (0xf << 12), pdev->usbecs);
+	}
+	if (mode == USB_IN_HOST_MOD) {
+		writel(readl(pdev->usbecs) & ((~0xf) << 12), pdev->usbecs);
+	}
+	return 0;
+}
+
+static void usb_hal_dp_up(usb_hal_monitor_t * pdev)
+{
+	return;
+}
+
+static void usb_hal_dp_down(usb_hal_monitor_t * pdev)
+{
+	return;
+}
+
+static int usb_hal_is_sof(usb_hal_monitor_t * pdev)
+{
+  return 0;
+}
+
+static int usb_hal_enable_irq(struct usb_hal_monitor *pdev, int enable)
+{
+	return 0;
+}
+
+static void usb_hal_debug(usb_hal_monitor_t * pdev)
+{
+	printk("%s:%d\n", __FILE__, __LINE__);
+	printk("pdev->usbecs addr: 0x%x\n\n", (unsigned int)pdev->usbecs);
+	return;
+}
+
+int usb_suspend_or_resume(usb_hal_monitor_t *pdev, int is_suspend)
+{
+	/* save/reload usbecs when suspend/resume */
+	if (is_suspend) {
+		pdev->usbecs_val = readl(pdev->usbecs);
+	}else{
+		usb_hardware_init(pdev);
+		//writel(pdev->usbecs_val, pdev->usbecs);
+	}	
+	return 0;
+}
+
+static void dwc3_controllor_init(usb_hal_monitor_t * pdev)
+{
+		
+	u32		reg;
+	int	ic_type =pdev->ic_type;
+
+	/*USB3 PLL enable*/
+	reg = readl(pdev->usbpll);
+       if(ic_type == IC_ATM7059A){
+	    reg |= (0x7f);
+       }
+       else if(ic_type == IC_ATM7039C){
+	    reg |= (0x1f);
+       }
+	writel(reg, pdev->usbpll);
+
+   	 udelay(1000);
+
+	/*USB3 Cmu Reset */
+	reg = readl(pdev->devrst);
+	reg &= ~(USB3_MOD_RST);
+	writel(reg, pdev->devrst);
+
+	udelay(500);
+
+	reg = readl(pdev->devrst);
+	reg |= (USB3_MOD_RST);
+	writel(reg, pdev->devrst);
+
+	udelay(500);
+
+ 	if(ic_type == IC_ATM7059A){
+
+		writel(0x6046, pdev->io_base+ANA02 );
+		writel(0x2010,pdev->io_base+ANA0E );
+		writel(0x8000,pdev->io_base+ANA0F );
+		writel(0x0, pdev->io_base+ REV1 );
+		writel(0x0013,pdev->io_base+PAGE1_REG02 );
+		writel(0x0004,pdev->io_base+PAGE1_REG06 );
+		writel(0x22ed,pdev->io_base+PAGE1_REG07 );
+		writel(0xf802, pdev->io_base+PAGE1_REG08 );
+		writel(0x3080,pdev->io_base+PAGE1_REG09 );
+		writel(0x2030, pdev->io_base+PAGE1_REG0B );
+		writel((1<<14), pdev->io_base+ANA0F );  
+             //enable bias
+            reg = readl(pdev->io_base + DWC3_CMU_DEBUG_LDO);
+		reg |= CMU_BIAS_EN;
+		writel(reg, pdev->io_base+ DWC3_CMU_DEBUG_LDO);
+        		/*USB2 LDO enable*/
+		reg = readl(pdev->usbecs );
+		reg |= (1 << USB3_P0_CTL_PLLLDOEN_IC1 )|(/*2*/3  << USB3_P0_CTL_LDOVREFSEL_SHIFT_IC1);
+		writel(reg, pdev->usbecs );	
+
+        
+	}
+	 else if(ic_type == IC_ATM7039C){
+		/*PLL1 enable*/
+		reg = readl(pdev->io_base + DWC3_CMU_DEBUG_LDO);
+		reg |= CMU_BIAS_EN;
+		writel(reg, pdev->io_base+ DWC3_CMU_DEBUG_LDO);
+
+		/*PLL2 enable*/
+		reg = (BIST_QINIT(0x3) | EYE_HEIGHT(0x4) | PLL2_LOCK | PLL2_RS(0x2) | 
+				PLL2_ICP(0x1) | CMU_SEL_PREDIV | CMU_DIVX2 | PLL2_DIV(0x17) | 
+				PLL2_POSTDIV(0x3) | PLL2_PU);
+		writel(reg, pdev->io_base + DWC3_CMU_PLL2_BISTDEBUG);
+		/*USB2 LDO enable*/
+		reg = readl(pdev->usbecs );
+		reg |= (1 << USB3_P0_CTL_PLLLDOEN )|(/*2*/3  << USB3_P0_CTL_LDOVREFSEL_SHIFT);
+		writel(reg, pdev->usbecs );	
+	}
+
+
+    
+	udelay(1000);
+
+}
+
+static void dwc3_controllor_exit(usb_hal_monitor_t * pdev)
+{
+	u32		reg;
+    
+	int	ic_type =pdev->ic_type;
+    
+	/*USB3 PLL disable*/
+	reg = readl(pdev->usbpll);
+	
+       if(ic_type == IC_ATM7059A){
+	    reg &= ~(0x7f);
+       }
+       else if(ic_type == IC_ATM7039C){
+	    reg &= ~(0x1f);
+       }
+	writel(reg, pdev->usbpll);
+}
+
+/*dwc3_controllor_otg_cfg\BA\AF\CA\FD\B5\F7\D3\C3\D3\D0\D2\D4\CF\C23\D6\D6\C7\E9\BF\F6;\D6\F7ҪĿ\B5\C4\CA\C7Ϊ\C1\CB\C9\E8\D6\C3\D6\F7\BF\D8\C6\F7\B4\A6\D3\DAotgģʽ;
+\D2Է\C0ֹid pin\B5\C4״̬\D4\DA\C6\E4\CB\FCģʽ\CF¼\EC\B2ⲻ׼.\B5\F7\D3õ\C4\C7\E9\BF\F6\C8\E7\CF\C2,resume\BA\AF\CA\FD,\BC\EC\B2⵽usb\B0γ\F6,\BC\EC\B2\E2
+\B5\BDu\C5̰γ\F6.*/
+/*dwc3_controllor_exit\BA\AF\CA\FD\BBὫusbpll\B9ص\F4,Ŀǰ\B7\A2\CF\D6\D3з\E7\CF\D5,\B2\BB\C4\DC\D4\DA\D5\E2\C0\EF\B5\F7\D3\C3.\D2\F2\B0\CE\CF\DF\C7\E9\BF\F6\CF\C2,
+dwc3(usb)\C7\FD\B6\AF\BF\C9\C4ܻ\B9δж\D4\D8,\B6\F8\C8\D4Ȼ\BF\C9\C4ܷ\C3\CE\CAusb\D6\F7\BF\D8\D6\C6\C6\F7,\B6\F8\D5\E2ʱ\D2Ѿ\AD\B9ص\F4\C1\CBpll,\BBᵼ\D6\C2\CE\CA\CC\E2.*/
+void __dwc3_controllor_mode_cfg(usb_hal_monitor_t *pdev)
+{
+//  u32 value;
+  /*\B2\BBΪ0,\B1\EDʾusb3֮ǰ\B5\C4Ƶ\C2ʴ\F2\BF\AA,\C7\FD\B6\AF\B4\E6\D4\DA;\B9\CA\D5\E2\B1߲\BB\D0\E8Ҫ\B4\F2\BF\AAƵ\C2\CA;\CD˳\F6ʱ\D2಻\D0\E8Ҫ\B9ر\D5Ƶ\C2\CA*/
+
+	dwc3_controllor_init(pdev);
+	mon_dwc3_set_mode(pdev, DWC3_GCTL_PRTCAP_OTG); 
+  
+#if 0     
+  if(value == 0)
+    dwc3_controllor_exit(pdev);
+#endif    
+
+}
+void dwc3_controllor_mode_cfg(usb_hal_monitor_t *pdev)
+{
+     return ;
+}
+int usb_hal_init_monitor_hw_ops(usb_hal_monitor_t * pdev, 
+	umon_port_config_t * config, unsigned int base)
+{
+	int ret = 0;
+	
+	pdev->name = "usb controller";
+	pdev->io_base =(void __iomem *) base;
+	pdev->usbecs = (void __iomem *)IO_ADDRESS(USB3_P0_CTL);
+	pdev->usbpll = (void __iomem *)IO_ADDRESS(CMU_USBPLL);
+	pdev->devrst =(void __iomem *)IO_ADDRESS( CMU_DEVRST1);
+
+	pdev->vbus_power_onoff = usb_monitor_vbus_power;
+	pdev->get_dc5v_state = usb_get_dc5v_state;
+	pdev->get_vbus_state = usb_get_vbus_state;
+	pdev->get_linestates = usb_get_linestates;
+	pdev->get_idpin_state = usb_get_idpin_state;
+	pdev->set_dp_500k_15k = usb_set_dp_500k_15k;
+	pdev->set_soft_id = usb_set_soft_id;
+	pdev->set_soft_vbus = usb_set_soft_vbus;
+	pdev->aotg_enable = usb_hal_aotg_enable;
+	pdev->set_mode = usb_hal_set_mode;
+	pdev->set_cmu_usbpll = usb_hal_set_cmu_usbpll;
+	pdev->dp_up = usb_hal_dp_up;
+	pdev->dp_down = usb_hal_dp_down;
+	pdev->is_sof = usb_hal_is_sof;
+	pdev->enable_irq = usb_hal_enable_irq;
+	pdev->debug = usb_hal_debug;
+	pdev->monitor_get_usb_plug_type = get_usb_plug_type;
+	pdev->suspend_or_resume = usb_suspend_or_resume;
+	pdev->dwc3_otg_mode_cfg = dwc3_controllor_mode_cfg;
+	pdev->dwc3_otg_exit = dwc3_controllor_exit;
+    pdev->dwc3_otg_init = dwc3_controllor_init;
+
+
+	pdev->config = config;
+	return ret;
+}
+
+
diff --git a/drivers/usb/monitor/umonitor_hal.h b/drivers/usb/monitor/umonitor_hal.h
new file mode 100644
index 0000000..8610878
--- /dev/null
+++ b/drivers/usb/monitor/umonitor_hal.h
@@ -0,0 +1,108 @@
+/*! \cond USBMONITOR*/
+/*********************************************************************************
+*                            Module: usb monitor driver
+*                (c) Copyright 2003 - 2008, Actions Co,Ld. 
+*                        All Right Reserved 
+*
+* History:        
+*      <author>      <time>       <version >    <desc>
+*       houjingkun   2011/07/08   1.0         build this file 
+********************************************************************************/ 
+/*!
+ * \file   umonitor_hal.h
+ * \brief  
+ *      usb monitor hardware opration api.
+ * \author houjingkun
+ * \par GENERAL DESCRIPTION:
+ * \par EXTERNALIZED FUNCTIONS:
+ *       null
+ *
+ *  Copyright(c) 2008-2012 Actions Semiconductor, All Rights Reserved.
+ *
+ * \version 1.0
+ * \date  2011/07/08
+ *******************************************************************************/
+#ifndef _UMONITOR_HAL_H_
+#define _UMONITOR_HAL_H_
+
+#include "umonitor_config.h"
+
+//VBUS detection threshold control. reg USB3_P0_CTL [1:0]
+#define VBUS_DET_THRESHOLD_LEVEL0     0x00    //4.22v
+#define VBUS_DET_THRESHOLD_LEVEL1     0x01    //4.00v
+#define VBUS_DET_THRESHOLD_LEVEL2     0x02    //3.65v
+#define VBUS_DET_THRESHOLD_LEVEL3     0x03    //3.11v
+
+typedef struct usb_hal_monitor {
+    char * name;
+    unsigned int usbecs_val;
+    void __iomem * io_base;
+    void __iomem * usbecs;
+    void __iomem * usbpll;
+    unsigned int usbpll_bits;
+    void __iomem * devrst;
+    unsigned int devrst_bits;
+    unsigned int devclk;
+    unsigned int devclk_bits;
+
+    umon_port_config_t * config;
+ 
+    int ic_type;
+    int (* vbus_power_onoff)(struct usb_hal_monitor *pdev, int is_on);
+
+    #define USB_DC5V_LOW               0
+    #define USB_DC5V_HIGH              1
+    #define USB_DC5V_INVALID           2
+    int (* get_dc5v_state)(struct usb_hal_monitor *pdev);
+    
+    #define USB_VBUS_LOW               0
+    #define USB_VBUS_HIGH              1
+    #define USB_VBUS_INVALID           2
+    int (* get_vbus_state)(struct usb_hal_monitor *pdev);
+    
+    /* return state of linestate[1:0]. */
+    unsigned int (* get_linestates)(struct usb_hal_monitor *pdev);
+    
+    /* 
+    * \BC\EC\B2\E2id pin\B5\C4״̬,\D6\F7Ҫ\BF\BC\C2\C7\D3\C3gpioȥ\D7\F7idpin\BC\EC\B2\E2\B5\C4\C7\E9\BF\F6,
+    * \C6\E4\CB\FB\C7\E9\BF\F6\B5\F7\D3ô˺\AF\CA\FDʱ\B7\B5\BB\D8Ϊ0 (\B1\EDʾ\BC\EC\B2\E2\CE\DEЧ).
+    * retval:
+    * USB_ID_STATE_INVALID -- \BC\EC\B2\E2\CE\DEЧ,\B4\CBʱ\B2\BB\D3ü\EC\B2\E2idpin\B5\C4״̬;
+    * USB_ID_STATE_DEVICE -- \BC\EC\B2⵽idpinΪ\B8\DF,\BD\F8\C8\EBdevice\BC\EC\B2\E2\BD׶\CE;
+    * USB_ID_STATE_HOST -- \BC\EC\B2⵽idpinΪ\B5\CD,\BD\F8\C8\EBhost\BC\EC\B2\E2\BD׶\CE;
+    */
+    #define USB_ID_STATE_INVALID    0
+    #define USB_ID_STATE_DEVICE     1
+    #define USB_ID_STATE_HOST       2
+    int (* get_idpin_state)(struct usb_hal_monitor *pdev);
+    
+    int (* set_dp_500k_15k)(struct usb_hal_monitor *pdev, int enable_500k_up, int enable_15k_down);
+    int (* set_soft_id)(struct usb_hal_monitor *pdev, int en_softid, int id_state);
+    int (* set_soft_vbus)(struct usb_hal_monitor *pdev, int en_softvbus, int vbus_state);
+    
+    int (* aotg_enable)(struct usb_hal_monitor *pdev, int enable);
+    
+    /* used for enter certain otg states. */
+    #define USB_IN_DEVICE_MOD   1
+    #define USB_IN_HOST_MOD     0
+    int (* set_mode)(struct usb_hal_monitor *pdev, int mode);
+    void (* dwc_set_mode)(struct usb_hal_monitor *pdev, int mode);
+    void (* set_cmu_usbpll)(struct usb_hal_monitor *pdev, int enable);
+    void (* dp_up)(struct usb_hal_monitor *pdev);
+    void (* dp_down)(struct usb_hal_monitor *pdev);
+    int (* is_sof)(struct usb_hal_monitor *pdev);
+    int (* enable_irq)(struct usb_hal_monitor *pdev, int enable);
+    int (* suspend_or_resume)(struct usb_hal_monitor *pdev, int is_suspend);
+    void (* dwc3_otg_mode_cfg)(struct usb_hal_monitor *pdev);
+    int (* monitor_get_usb_plug_type)(struct usb_hal_monitor *pdev);
+    void (* dwc3_otg_init)(struct usb_hal_monitor *pdev);
+    void (* dwc3_otg_exit)(struct usb_hal_monitor *pdev);
+    void (* debug)(struct usb_hal_monitor *pdev);
+} usb_hal_monitor_t;
+
+int usb_hal_init_monitor_hw_ops(usb_hal_monitor_t * pdev, umon_port_config_t * config, unsigned int base);
+
+/* todo */
+
+#endif  /* _UMONITOR_HAL_H_ */
+/*! \endcond*/
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
old mode 100644
new mode 100755
index a599e8a..8f00195
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -82,9 +82,85 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_VENDOR_ID			0x12D1
 #define HUAWEI_PRODUCT_E173			0x140C
 #define HUAWEI_PRODUCT_E1750			0x1406
+#define HUAWEI_PRODUCT_E600			0x1001
+#define HUAWEI_PRODUCT_E220			0x1003
+#define HUAWEI_PRODUCT_E220BIS			0x1004
+#define HUAWEI_PRODUCT_E1401			0x1401
+#define HUAWEI_PRODUCT_E1402			0x1402
+#define HUAWEI_PRODUCT_E1403			0x1403
+#define HUAWEI_PRODUCT_E1404			0x1404
+#define HUAWEI_PRODUCT_E1405			0x1405
+#define HUAWEI_PRODUCT_E1406			0x1406
+#define HUAWEI_PRODUCT_E1407			0x1407
+#define HUAWEI_PRODUCT_E1408			0x1408
+#define HUAWEI_PRODUCT_E1409			0x1409
+#define HUAWEI_PRODUCT_E140A			0x140A
+#define HUAWEI_PRODUCT_E140B			0x140B
+#define HUAWEI_PRODUCT_E140C			0x140C
+#define HUAWEI_PRODUCT_E140D			0x140D
+#define HUAWEI_PRODUCT_E140E			0x140E
+#define HUAWEI_PRODUCT_E140F			0x140F
+#define HUAWEI_PRODUCT_E1410			0x1410
+#define HUAWEI_PRODUCT_E1411			0x1411
+#define HUAWEI_PRODUCT_E1412			0x1412
+#define HUAWEI_PRODUCT_E1413			0x1413
+#define HUAWEI_PRODUCT_E1414			0x1414
+#define HUAWEI_PRODUCT_E1415			0x1415
+#define HUAWEI_PRODUCT_E1416			0x1416
+#define HUAWEI_PRODUCT_E1417			0x1417
+#define HUAWEI_PRODUCT_E1418			0x1418
+#define HUAWEI_PRODUCT_E1419			0x1419
+#define HUAWEI_PRODUCT_E141A			0x141A
+#define HUAWEI_PRODUCT_E141B			0x141B
+#define HUAWEI_PRODUCT_E141C			0x141C
+#define HUAWEI_PRODUCT_E141D			0x141D
+#define HUAWEI_PRODUCT_E141E			0x141E
+#define HUAWEI_PRODUCT_E141F			0x141F
+#define HUAWEI_PRODUCT_E1420			0x1420
+#define HUAWEI_PRODUCT_E1421			0x1421
+#define HUAWEI_PRODUCT_E1422			0x1422
+#define HUAWEI_PRODUCT_E1423			0x1423
+#define HUAWEI_PRODUCT_E1424			0x1424
+#define HUAWEI_PRODUCT_E1425			0x1425
+#define HUAWEI_PRODUCT_E1426			0x1426
+#define HUAWEI_PRODUCT_E1427			0x1427
+#define HUAWEI_PRODUCT_E1428			0x1428
+#define HUAWEI_PRODUCT_E1429			0x1429
+#define HUAWEI_PRODUCT_E142A			0x142A
+#define HUAWEI_PRODUCT_E142B			0x142B
+#define HUAWEI_PRODUCT_E142C			0x142C
+#define HUAWEI_PRODUCT_E142D			0x142D
+#define HUAWEI_PRODUCT_E142E			0x142E
+#define HUAWEI_PRODUCT_E142F			0x142F
+#define HUAWEI_PRODUCT_E1430			0x1430
+#define HUAWEI_PRODUCT_E1431			0x1431
+#define HUAWEI_PRODUCT_E1432			0x1432
+#define HUAWEI_PRODUCT_E1433			0x1433
+#define HUAWEI_PRODUCT_E1434			0x1434
+#define HUAWEI_PRODUCT_E1435			0x1435
+#define HUAWEI_PRODUCT_E1436			0x1436
+#define HUAWEI_PRODUCT_E1437			0x1437
+#define HUAWEI_PRODUCT_E1438			0x1438
+#define HUAWEI_PRODUCT_E1439			0x1439
+#define HUAWEI_PRODUCT_E143A			0x143A
+#define HUAWEI_PRODUCT_E143B			0x143B
+#define HUAWEI_PRODUCT_E143C			0x143C
+#define HUAWEI_PRODUCT_E143D			0x143D
+#define HUAWEI_PRODUCT_E143E			0x143E
+#define HUAWEI_PRODUCT_E143F			0x143F
 #define HUAWEI_PRODUCT_K4505			0x1464
 #define HUAWEI_PRODUCT_K3765			0x1465
+#define HUAWEI_PRODUCT_E14AC			0x14AC
+#define HUAWEI_PRODUCT_K3806			0x14AE
 #define HUAWEI_PRODUCT_K4605			0x14C6
+#define HUAWEI_PRODUCT_K5005			0x14C8
+#define HUAWEI_PRODUCT_K3770			0x14C9
+#define HUAWEI_PRODUCT_K3771			0x14CA
+#define HUAWEI_PRODUCT_K4510			0x14CB
+#define HUAWEI_PRODUCT_K4511			0x14CC
+#define HUAWEI_PRODUCT_ETS1220			0x1803
+#define HUAWEI_PRODUCT_E353			0x1506
+#define HUAWEI_PRODUCT_E173S			0x1C05
 #define HUAWEI_PRODUCT_E173S6			0x1C07
 
 #define QUANTA_VENDOR_ID			0x0408
@@ -160,6 +236,8 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED	0x8001
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED	0x9000
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED	0x9001
+#define NOVATELWIRELESS_PRODUCT_G1		0xA001
+#define NOVATELWIRELESS_PRODUCT_G1_M		0xA002
 #define NOVATELWIRELESS_PRODUCT_E362		0x9010
 #define NOVATELWIRELESS_PRODUCT_E371		0x9011
 #define NOVATELWIRELESS_PRODUCT_U620L		0x9022
@@ -289,11 +367,15 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF622			0x0001
 #define ZTE_PRODUCT_MF628			0x0015
 #define ZTE_PRODUCT_MF626			0x0031
+#define ZTE_PRODUCT_CDMA_TECH			0xfffe
+#define ZTE_PRODUCT_AC8710			0xfff1
+#define ZTE_PRODUCT_AC2726			0xfff5
 #define ZTE_PRODUCT_ZM8620_X			0x0396
 #define ZTE_PRODUCT_ME3620_MBIM			0x0426
 #define ZTE_PRODUCT_ME3620_X			0x1432
 #define ZTE_PRODUCT_ME3620_L			0x1433
-#define ZTE_PRODUCT_AC2726			0xfff1
+#define ZTE_PRODUCT_AD3812			0xffeb
+#define ZTE_PRODUCT_MC2716			0xffed
 #define ZTE_PRODUCT_MG880			0xfffd
 #define ZTE_PRODUCT_CDMA_TECH			0xfffe
 #define ZTE_PRODUCT_AC8710T			0xffff
@@ -370,6 +452,7 @@ static void option_instat_callback(struct urb *urb);
  * It seems to contain a Qualcomm QSC6240/6290 chipset            */
 #define FOUR_G_SYSTEMS_PRODUCT_W14		0x9603
 #define FOUR_G_SYSTEMS_PRODUCT_W100		0x9b01
+#define FOUR_G_SYSTEMS_PRODUCT_MMX350G		0x9800
 
 /* iBall 3.5G connect wireless modem */
 #define IBALL_3_5G_CONNECT			0x9605
@@ -377,6 +460,28 @@ static void option_instat_callback(struct urb *urb);
 /* Zoom */
 #define ZOOM_PRODUCT_4597			0x9607
 
+#define MICROMAX_VENDOR_ID 0x2020
+#define MICROMAX_1_PID 0x4010
+#define MICROMAX_MT6229 0x2000
+
+/* India */
+#define INDIA_VENDOR_ID 0x1dbc 
+#define MMX355G 0x0669
+
+#define CHINA_TELECOM 0x15eb 
+#define CHINA_TELECOM_CBP71 0x7152
+
+#define OLICARD_VID 0x0b3c 
+#define OLICARD160_PID 0xc00a
+
+/*WM66E*/
+#define SMART_BRO_WM66E		0x9803
+/*MMX 3536*/
+#define MMX_PID_3536		0x9605
+/*MMX310*/
+#define MMX_PID_310		0x9e00
+#define MMX_PID_6003            0x6003
+
 /* SpeedUp SU9800 usb 3g modem */
 #define SPEEDUP_PRODUCT_SU9800			0x9800
 
@@ -384,6 +489,7 @@ static void option_instat_callback(struct urb *urb);
 #define HAIER_VENDOR_ID				0x201e
 #define HAIER_PRODUCT_CE81B			0x10f8
 #define HAIER_PRODUCT_CE100			0x2009
+#define SMARTFREN_CE682 			0x1022
 
 /* Gemalto's Cinterion products (formerly Siemens) */
 #define SIEMENS_VENDOR_ID			0x0681
@@ -417,10 +523,26 @@ static void option_instat_callback(struct urb *urb);
 #define CELOT_VENDOR_ID				0x211f
 #define CELOT_PRODUCT_CT680M			0x6801
 
+/* ONDA Communication vendor id */
+#define ONDA_VENDOR_ID       0x1ee8
+
+/* ONDA MT825UP HSDPA 14.2 modem */
+#define ONDA_MT825UP         0x000b
+
 /* Samsung products */
 #define SAMSUNG_VENDOR_ID                       0x04e8
 #define SAMSUNG_PRODUCT_GT_B3730                0x6889
 
+/* USI 3G */ 
+#define USI_VENDOR_ID                0x0e8d
+#define USI_PRODUCT_WCDMA_3COM       0x00a1
+#define USI_PRODUCT_WCDMA_2COM       0x00a2
+
+/* Spreadwin add by liuyalong*/
+#define SPREADWIN_VENDOR_ID 			0x1782
+#define SPREADWIN_PRODUCT_G67   		0x0002
+#define SPREADWIN_PRODUCT_G67_DEBUG		0x4d00
+
 /* YUGA products  www.yuga-info.com gavin.kx at qq.com */
 #define YUGA_VENDOR_ID				0x257A
 #define YUGA_PRODUCT_CEM600			0x1601
@@ -524,6 +646,15 @@ static void option_instat_callback(struct urb *urb);
 #define INOVIA_VENDOR_ID			0x20a6
 #define INOVIA_SEW858				0x1105
 
+/* STRONGRISING products */
+#define STRONGRISING_VENDOR_ID_W		0x20a6
+#define STRONGRISING_PRODUCT_ID_W		0x1105
+
+#define STRONGRISING_VENDOR_ID_TD		0x21f5
+#define STRONGRISING_PRODUCT_ID_TD		0x1101
+#define STRONGRISING_PRODUCT_MODEM_EVDO		0x2009
+#define STRONGRISING_PRODUCT_MODEM_WCDMA	0x2012
+
 /* VIA Telecom */
 #define VIATELECOM_VENDOR_ID			0x15eb
 #define VIATELECOM_PRODUCT_CDS7			0x0001
@@ -719,6 +850,104 @@ static const struct usb_device_id option_ids[] = {
 		.driver_info = (kernel_ulong_t) &net_intf1_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) },  /* E398 3G Modem */
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) },  /* E398 3G PC UI Interface */
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) },  /* E398 3G Application Interface */
 	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) },
 	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) },
 	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) },
@@ -1106,6 +1335,8 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) },
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) },
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
 	/* Novatel Ovation MC551 a.k.a. Verizon USB551L */
 	{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
@@ -1219,6 +1450,7 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+	{ USB_DEVICE(OLICARD_VID, OLICARD160_PID) },//alic
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
 		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
@@ -1800,6 +2032,7 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xfffc, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MG880, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff),
@@ -1808,6 +2041,10 @@ static const struct usb_device_id option_ids[] = {
 	 .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
 	 .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff),
+	 .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
+	 .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_L),
 	 .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_MBIM),
@@ -1853,6 +2090,7 @@ static const struct usb_device_id option_ids[] = {
 	  .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
 	{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
 	{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
+	{ USB_DEVICE(INDIA_VENDOR_ID, MMX355G), 0x0a, 0x00, 0x00 },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
   	  .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
   	},
@@ -1860,10 +2098,19 @@ static const struct usb_device_id option_ids[] = {
 	  .driver_info = (kernel_ulong_t)&four_g_w100_blacklist
 	},
 	{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) },
+	{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_MMX350G) },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
+	{ USB_DEVICE(LONGCHEER_VENDOR_ID, SMART_BRO_WM66E) },
+	{ USB_DEVICE(LONGCHEER_VENDOR_ID, MMX_PID_3536) },
+	{ USB_DEVICE(LONGCHEER_VENDOR_ID, MMX_PID_310) },
+	{ USB_DEVICE(LONGCHEER_VENDOR_ID, MMX_PID_6003) },
 	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HAIER_VENDOR_ID, HAIER_PRODUCT_CE81B, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE(HAIER_VENDOR_ID, SMARTFREN_CE682) },
+	{ USB_DEVICE(CHINA_TELECOM, CHINA_TELECOM_CBP71) },
+	{ USB_DEVICE(MICROMAX_VENDOR_ID, MICROMAX_1_PID) },
+	{ USB_DEVICE(MICROMAX_VENDOR_ID, MICROMAX_MT6229) },
 	/* Pirelli  */
 	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
 	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
@@ -1917,7 +2164,12 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD500),
 		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
 	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
+	{ USB_DEVICE(USI_VENDOR_ID, USI_PRODUCT_WCDMA_3COM) },	/* USI WCDMA modem 3COM */
+	{ USB_DEVICE(USI_VENDOR_ID, USI_PRODUCT_WCDMA_2COM) },	/* USI WCDMA modem 2COM */
+	{ USB_DEVICE(SPREADWIN_VENDOR_ID, SPREADWIN_PRODUCT_G67) },
+	{ USB_DEVICE(SPREADWIN_VENDOR_ID, SPREADWIN_PRODUCT_G67_DEBUG) },
 	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
 	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) },
 	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM500) },
@@ -1988,6 +2240,10 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
 	{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
+	{ USB_DEVICE(STRONGRISING_VENDOR_ID_W, STRONGRISING_PRODUCT_ID_W) },
+	{ USB_DEVICE(STRONGRISING_VENDOR_ID_TD, STRONGRISING_PRODUCT_ID_TD) },
+	{ USB_DEVICE(STRONGRISING_VENDOR_ID_TD, STRONGRISING_PRODUCT_MODEM_EVDO) },
+	{ USB_DEVICE(STRONGRISING_VENDOR_ID_TD, STRONGRISING_PRODUCT_MODEM_WCDMA) },
 	{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) },
 	{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) },
 	{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
@@ -2143,6 +2399,7 @@ static void option_release(struct usb_serial *serial)
 static void option_instat_callback(struct urb *urb)
 {
 	int err;
+    	static int cnt=0;
 	int status = urb->status;
 	struct usb_serial_port *port = urb->context;
 	struct device *dev = &port->dev;
@@ -2187,6 +2444,19 @@ static void option_instat_callback(struct urb *urb)
 
 	/* Resubmit urb so we continue receiving IRQ data */
 	if (status != -ESHUTDOWN && status != -ENOENT) {
+		/* fix the bug when plug-out dongle will always print
+		   option_instat_callback: error -71 */
+		if(status == -EPROTO){
+			cnt++;
+			if(cnt > 10){
+				cnt =  0;
+				return;
+			}
+			
+		}	
+		else{
+			cnt =  0;
+		}	
 		usb_mark_last_busy(port->serial->dev);
 		err = usb_submit_urb(urb, GFP_ATOMIC);
 		if (err)
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
old mode 100644
new mode 100755
index ba8f759..0d95ac9
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -90,6 +90,17 @@ module_param_string(quirks, quirks, sizeof(quirks), S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
 
 
+#define DEBUG_TIME_OF_SCSI_CMDS 1
+#if DEBUG_TIME_OF_SCSI_CMDS
+static unsigned int total_usec_time_of_scsi_cmds = 0;
+module_param(total_usec_time_of_scsi_cmds, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(total_usec_time_of_scsi_cmds, "total_usec_time_of_scsi_cmds");
+
+static unsigned int debug_cmds_time = 0;
+module_param(debug_cmds_time, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug_cmds_time, "debug_cmds_time");
+#endif
+
 /*
  * The entries in this table correspond, line for line,
  * with the entries in usb_storage_usb_ids[], defined in usual-tables.c.
@@ -375,8 +386,30 @@ static int usb_stor_control_thread(void * __us)
 
 		/* we've got a command, let's do it! */
 		else {
+#if DEBUG_TIME_OF_SCSI_CMDS
+			struct timeval tv_start;
+			struct timeval tv_end;
+#endif
+
 			US_DEBUG(usb_stor_show_command(us, us->srb));
+
+#if DEBUG_TIME_OF_SCSI_CMDS
+			if(debug_cmds_time) {
+				do_gettimeofday(&tv_start);
+			}
+#endif
 			us->proto_handler(us->srb, us);
+#if DEBUG_TIME_OF_SCSI_CMDS
+			if(debug_cmds_time) {
+				do_gettimeofday(&tv_end);
+				if(tv_end.tv_sec > tv_start.tv_sec) {
+					total_usec_time_of_scsi_cmds += ((tv_end.tv_sec - tv_start.tv_sec)*1000000 + tv_end.tv_usec - tv_start.tv_usec);
+				}
+				else {
+					total_usec_time_of_scsi_cmds += (tv_end.tv_usec - tv_start.tv_usec);
+				}
+			}
+#endif
 			usb_mark_last_busy(us->pusb_dev);
 		}
 
-- 
2.7.4



More information about the linux-yocto mailing list