diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index ed90aef404c3..9c97d7ca389c 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -44,6 +44,7 @@
 #include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/ehci.h>
+#include <linux/platform_data/s3c-hsotg.h>
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index cb2b027f09a6..62f159a6583c 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -42,6 +42,7 @@
 #include <plat/fimc-core.h>
 #include <plat/camport.h>
 #include <plat/mipi_csis.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <mach/map.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index e20bf5835365..a02f204d99ed 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -61,7 +61,7 @@
 #include <plat/sdhci.h>
 #include <plat/gpio-cfg.h>
 #include <plat/s3c64xx-spi.h>
-#include <plat/udc-hs.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <plat/keypad.h>
 #include <plat/clock.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index ce745e19aa27..ee0d13c98378 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -33,7 +33,7 @@
 #include <plat/gpio-cfg.h>
 #include <plat/hwmon.h>
 #include <plat/regs-serial.h>
-#include <plat/udc-hs.h>
+#include <linux/platform_data/s3c-hsotg.h>
 #include <plat/usb-control.h>
 #include <plat/sdhci.h>
 #include <plat/ts.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index d55bc96d9582..bf477e33f0ee 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -72,7 +72,7 @@
 #include <plat/keypad.h>
 #include <plat/backlight.h>
 #include <plat/regs-fb-v4.h>
-#include <plat/udc-hs.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 32395664e879..781fed689cd8 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -50,6 +50,7 @@
 #include <plat/mfc.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/camport.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <media/v4l2-mediabus.h>
 #include <media/s5p_fimc.h>
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 8b928f9bc1c3..a41c808847c0 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -57,7 +57,7 @@
 #include <plat/sdhci.h>
 #include <plat/ts.h>
 #include <plat/udc.h>
-#include <plat/udc-hs.h>
+#include <linux/platform_data/s3c-hsotg.h>
 #include <plat/usb-control.h>
 #include <plat/usb-phy.h>
 #include <plat/regs-iic.h>
diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
deleted file mode 100644
index dc90f5ede88f..000000000000
--- a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - USB2.0 Highspeed/OtG device block registers
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_H
-#define __PLAT_S3C64XX_REGS_USB_HSOTG_H __FILE__
-
-#define S3C_HSOTG_REG(x) (x)
-
-#define S3C_GOTGCTL				S3C_HSOTG_REG(0x000)
-#define S3C_GOTGCTL_BSESVLD			(1 << 19)
-#define S3C_GOTGCTL_ASESVLD			(1 << 18)
-#define S3C_GOTGCTL_DBNC_SHORT			(1 << 17)
-#define S3C_GOTGCTL_CONID_B			(1 << 16)
-#define S3C_GOTGCTL_DEVHNPEN			(1 << 11)
-#define S3C_GOTGCTL_HSSETHNPEN			(1 << 10)
-#define S3C_GOTGCTL_HNPREQ			(1 << 9)
-#define S3C_GOTGCTL_HSTNEGSCS			(1 << 8)
-#define S3C_GOTGCTL_SESREQ			(1 << 1)
-#define S3C_GOTGCTL_SESREQSCS			(1 << 0)
-
-#define S3C_GOTGINT				S3C_HSOTG_REG(0x004)
-#define S3C_GOTGINT_DbnceDone			(1 << 19)
-#define S3C_GOTGINT_ADevTOUTChg			(1 << 18)
-#define S3C_GOTGINT_HstNegDet			(1 << 17)
-#define S3C_GOTGINT_HstnegSucStsChng		(1 << 9)
-#define S3C_GOTGINT_SesReqSucStsChng		(1 << 8)
-#define S3C_GOTGINT_SesEndDet			(1 << 2)
-
-#define S3C_GAHBCFG				S3C_HSOTG_REG(0x008)
-#define S3C_GAHBCFG_PTxFEmpLvl			(1 << 8)
-#define S3C_GAHBCFG_NPTxFEmpLvl			(1 << 7)
-#define S3C_GAHBCFG_DMAEn			(1 << 5)
-#define S3C_GAHBCFG_HBstLen_MASK		(0xf << 1)
-#define S3C_GAHBCFG_HBstLen_SHIFT		(1)
-#define S3C_GAHBCFG_HBstLen_Single		(0x0 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr		(0x1 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr4		(0x3 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr8		(0x5 << 1)
-#define S3C_GAHBCFG_HBstLen_Incr16		(0x7 << 1)
-#define S3C_GAHBCFG_GlblIntrEn			(1 << 0)
-
-#define S3C_GUSBCFG				S3C_HSOTG_REG(0x00C)
-#define S3C_GUSBCFG_PHYLPClkSel			(1 << 15)
-#define S3C_GUSBCFG_HNPCap			(1 << 9)
-#define S3C_GUSBCFG_SRPCap			(1 << 8)
-#define S3C_GUSBCFG_PHYIf16			(1 << 3)
-#define S3C_GUSBCFG_TOutCal_MASK		(0x7 << 0)
-#define S3C_GUSBCFG_TOutCal_SHIFT		(0)
-#define S3C_GUSBCFG_TOutCal_LIMIT		(0x7)
-#define S3C_GUSBCFG_TOutCal(_x)			((_x) << 0)
-
-#define S3C_GRSTCTL				S3C_HSOTG_REG(0x010)
-
-#define S3C_GRSTCTL_AHBIdle			(1 << 31)
-#define S3C_GRSTCTL_DMAReq			(1 << 30)
-#define S3C_GRSTCTL_TxFNum_MASK			(0x1f << 6)
-#define S3C_GRSTCTL_TxFNum_SHIFT		(6)
-#define S3C_GRSTCTL_TxFNum_LIMIT		(0x1f)
-#define S3C_GRSTCTL_TxFNum(_x)			((_x) << 6)
-#define S3C_GRSTCTL_TxFFlsh			(1 << 5)
-#define S3C_GRSTCTL_RxFFlsh			(1 << 4)
-#define S3C_GRSTCTL_INTknQFlsh			(1 << 3)
-#define S3C_GRSTCTL_FrmCntrRst			(1 << 2)
-#define S3C_GRSTCTL_HSftRst			(1 << 1)
-#define S3C_GRSTCTL_CSftRst			(1 << 0)
-
-#define S3C_GINTSTS				S3C_HSOTG_REG(0x014)
-#define S3C_GINTMSK				S3C_HSOTG_REG(0x018)
-
-#define S3C_GINTSTS_WkUpInt			(1 << 31)
-#define S3C_GINTSTS_SessReqInt			(1 << 30)
-#define S3C_GINTSTS_DisconnInt			(1 << 29)
-#define S3C_GINTSTS_ConIDStsChng		(1 << 28)
-#define S3C_GINTSTS_PTxFEmp			(1 << 26)
-#define S3C_GINTSTS_HChInt			(1 << 25)
-#define S3C_GINTSTS_PrtInt			(1 << 24)
-#define S3C_GINTSTS_FetSusp			(1 << 22)
-#define S3C_GINTSTS_incompIP			(1 << 21)
-#define S3C_GINTSTS_IncomplSOIN			(1 << 20)
-#define S3C_GINTSTS_OEPInt			(1 << 19)
-#define S3C_GINTSTS_IEPInt			(1 << 18)
-#define S3C_GINTSTS_EPMis			(1 << 17)
-#define S3C_GINTSTS_EOPF			(1 << 15)
-#define S3C_GINTSTS_ISOutDrop			(1 << 14)
-#define S3C_GINTSTS_EnumDone			(1 << 13)
-#define S3C_GINTSTS_USBRst			(1 << 12)
-#define S3C_GINTSTS_USBSusp			(1 << 11)
-#define S3C_GINTSTS_ErlySusp			(1 << 10)
-#define S3C_GINTSTS_GOUTNakEff			(1 << 7)
-#define S3C_GINTSTS_GINNakEff			(1 << 6)
-#define S3C_GINTSTS_NPTxFEmp			(1 << 5)
-#define S3C_GINTSTS_RxFLvl			(1 << 4)
-#define S3C_GINTSTS_SOF				(1 << 3)
-#define S3C_GINTSTS_OTGInt			(1 << 2)
-#define S3C_GINTSTS_ModeMis			(1 << 1)
-#define S3C_GINTSTS_CurMod_Host			(1 << 0)
-
-#define S3C_GRXSTSR				S3C_HSOTG_REG(0x01C)
-#define S3C_GRXSTSP				S3C_HSOTG_REG(0x020)
-
-#define S3C_GRXSTS_FN_MASK			(0x7f << 25)
-#define S3C_GRXSTS_FN_SHIFT			(25)
-
-#define S3C_GRXSTS_PktSts_MASK			(0xf << 17)
-#define S3C_GRXSTS_PktSts_SHIFT			(17)
-#define S3C_GRXSTS_PktSts_GlobalOutNAK		(0x1 << 17)
-#define S3C_GRXSTS_PktSts_OutRX			(0x2 << 17)
-#define S3C_GRXSTS_PktSts_OutDone		(0x3 << 17)
-#define S3C_GRXSTS_PktSts_SetupDone		(0x4 << 17)
-#define S3C_GRXSTS_PktSts_SetupRX		(0x6 << 17)
-
-#define S3C_GRXSTS_DPID_MASK			(0x3 << 15)
-#define S3C_GRXSTS_DPID_SHIFT			(15)
-#define S3C_GRXSTS_ByteCnt_MASK			(0x7ff << 4)
-#define S3C_GRXSTS_ByteCnt_SHIFT		(4)
-#define S3C_GRXSTS_EPNum_MASK			(0xf << 0)
-#define S3C_GRXSTS_EPNum_SHIFT			(0)
-
-#define S3C_GRXFSIZ				S3C_HSOTG_REG(0x024)
-
-#define S3C_GNPTXFSIZ				S3C_HSOTG_REG(0x028)
-
-#define S3C_GNPTXFSIZ_NPTxFDep_MASK		(0xffff << 16)
-#define S3C_GNPTXFSIZ_NPTxFDep_SHIFT		(16)
-#define S3C_GNPTXFSIZ_NPTxFDep_LIMIT		(0xffff)
-#define S3C_GNPTXFSIZ_NPTxFDep(_x)		((_x) << 16)
-#define S3C_GNPTXFSIZ_NPTxFStAddr_MASK		(0xffff << 0)
-#define S3C_GNPTXFSIZ_NPTxFStAddr_SHIFT		(0)
-#define S3C_GNPTXFSIZ_NPTxFStAddr_LIMIT		(0xffff)
-#define S3C_GNPTXFSIZ_NPTxFStAddr(_x)		((_x) << 0)
-
-#define S3C_GNPTXSTS				S3C_HSOTG_REG(0x02C)
-
-#define S3C_GNPTXSTS_NPtxQTop_MASK		(0x7f << 24)
-#define S3C_GNPTXSTS_NPtxQTop_SHIFT		(24)
-
-#define S3C_GNPTXSTS_NPTxQSpcAvail_MASK		(0xff << 16)
-#define S3C_GNPTXSTS_NPTxQSpcAvail_SHIFT	(16)
-#define S3C_GNPTXSTS_NPTxQSpcAvail_GET(_v)	(((_v) >> 16) & 0xff)
-
-#define S3C_GNPTXSTS_NPTxFSpcAvail_MASK		(0xffff << 0)
-#define S3C_GNPTXSTS_NPTxFSpcAvail_SHIFT	(0)
-#define S3C_GNPTXSTS_NPTxFSpcAvail_GET(_v)	(((_v) >> 0) & 0xffff)
-
-
-#define S3C_HPTXFSIZ				S3C_HSOTG_REG(0x100)
-
-#define S3C_DPTXFSIZn(_a)			S3C_HSOTG_REG(0x104 + (((_a) - 1) * 4))
-
-#define S3C_DPTXFSIZn_DPTxFSize_MASK		(0xffff << 16)
-#define S3C_DPTXFSIZn_DPTxFSize_SHIFT		(16)
-#define S3C_DPTXFSIZn_DPTxFSize_GET(_v)		(((_v) >> 16) & 0xffff)
-#define S3C_DPTXFSIZn_DPTxFSize_LIMIT		(0xffff)
-#define S3C_DPTXFSIZn_DPTxFSize(_x)		((_x) << 16)
-
-#define S3C_DPTXFSIZn_DPTxFStAddr_MASK		(0xffff << 0)
-#define S3C_DPTXFSIZn_DPTxFStAddr_SHIFT		(0)
-
-/* Device mode registers */
-#define S3C_DCFG				S3C_HSOTG_REG(0x800)
-
-#define S3C_DCFG_EPMisCnt_MASK			(0x1f << 18)
-#define S3C_DCFG_EPMisCnt_SHIFT			(18)
-#define S3C_DCFG_EPMisCnt_LIMIT			(0x1f)
-#define S3C_DCFG_EPMisCnt(_x)			((_x) << 18)
-
-#define S3C_DCFG_PerFrInt_MASK			(0x3 << 11)
-#define S3C_DCFG_PerFrInt_SHIFT			(11)
-#define S3C_DCFG_PerFrInt_LIMIT			(0x3)
-#define S3C_DCFG_PerFrInt(_x)			((_x) << 11)
-
-#define S3C_DCFG_DevAddr_MASK			(0x7f << 4)
-#define S3C_DCFG_DevAddr_SHIFT			(4)
-#define S3C_DCFG_DevAddr_LIMIT			(0x7f)
-#define S3C_DCFG_DevAddr(_x)			((_x) << 4)
-
-#define S3C_DCFG_NZStsOUTHShk			(1 << 2)
-
-#define S3C_DCFG_DevSpd_MASK			(0x3 << 0)
-#define S3C_DCFG_DevSpd_SHIFT			(0)
-#define S3C_DCFG_DevSpd_HS			(0x0 << 0)
-#define S3C_DCFG_DevSpd_FS			(0x1 << 0)
-#define S3C_DCFG_DevSpd_LS			(0x2 << 0)
-#define S3C_DCFG_DevSpd_FS48			(0x3 << 0)
-
-#define S3C_DCTL				S3C_HSOTG_REG(0x804)
-
-#define S3C_DCTL_PWROnPrgDone			(1 << 11)
-#define S3C_DCTL_CGOUTNak			(1 << 10)
-#define S3C_DCTL_SGOUTNak			(1 << 9)
-#define S3C_DCTL_CGNPInNAK			(1 << 8)
-#define S3C_DCTL_SGNPInNAK			(1 << 7)
-#define S3C_DCTL_TstCtl_MASK			(0x7 << 4)
-#define S3C_DCTL_TstCtl_SHIFT			(4)
-#define S3C_DCTL_GOUTNakSts			(1 << 3)
-#define S3C_DCTL_GNPINNakSts			(1 << 2)
-#define S3C_DCTL_SftDiscon			(1 << 1)
-#define S3C_DCTL_RmtWkUpSig			(1 << 0)
-
-#define S3C_DSTS				S3C_HSOTG_REG(0x808)
-
-#define S3C_DSTS_SOFFN_MASK			(0x3fff << 8)
-#define S3C_DSTS_SOFFN_SHIFT			(8)
-#define S3C_DSTS_SOFFN_LIMIT			(0x3fff)
-#define S3C_DSTS_SOFFN(_x)			((_x) << 8)
-#define S3C_DSTS_ErraticErr			(1 << 3)
-#define S3C_DSTS_EnumSpd_MASK			(0x3 << 1)
-#define S3C_DSTS_EnumSpd_SHIFT			(1)
-#define S3C_DSTS_EnumSpd_HS			(0x0 << 1)
-#define S3C_DSTS_EnumSpd_FS			(0x1 << 1)
-#define S3C_DSTS_EnumSpd_LS			(0x2 << 1)
-#define S3C_DSTS_EnumSpd_FS48			(0x3 << 1)
-
-#define S3C_DSTS_SuspSts			(1 << 0)
-
-#define S3C_DIEPMSK				S3C_HSOTG_REG(0x810)
-
-#define S3C_DIEPMSK_TxFIFOEmpty			(1 << 7)
-#define S3C_DIEPMSK_INEPNakEffMsk		(1 << 6)
-#define S3C_DIEPMSK_INTknEPMisMsk		(1 << 5)
-#define S3C_DIEPMSK_INTknTXFEmpMsk		(1 << 4)
-#define S3C_DIEPMSK_TimeOUTMsk			(1 << 3)
-#define S3C_DIEPMSK_AHBErrMsk			(1 << 2)
-#define S3C_DIEPMSK_EPDisbldMsk			(1 << 1)
-#define S3C_DIEPMSK_XferComplMsk		(1 << 0)
-
-#define S3C_DOEPMSK				S3C_HSOTG_REG(0x814)
-
-#define S3C_DOEPMSK_Back2BackSetup		(1 << 6)
-#define S3C_DOEPMSK_OUTTknEPdisMsk		(1 << 4)
-#define S3C_DOEPMSK_SetupMsk			(1 << 3)
-#define S3C_DOEPMSK_AHBErrMsk			(1 << 2)
-#define S3C_DOEPMSK_EPDisbldMsk			(1 << 1)
-#define S3C_DOEPMSK_XferComplMsk		(1 << 0)
-
-#define S3C_DAINT				S3C_HSOTG_REG(0x818)
-#define S3C_DAINTMSK				S3C_HSOTG_REG(0x81C)
-
-#define S3C_DAINT_OutEP_SHIFT			(16)
-#define S3C_DAINT_OutEP(x)			(1 << ((x) + 16))
-#define S3C_DAINT_InEP(x)			(1 << (x))
-
-#define S3C_DTKNQR1				S3C_HSOTG_REG(0x820)
-#define S3C_DTKNQR2				S3C_HSOTG_REG(0x824)
-#define S3C_DTKNQR3				S3C_HSOTG_REG(0x830)
-#define S3C_DTKNQR4				S3C_HSOTG_REG(0x834)
-
-#define S3C_DVBUSDIS				S3C_HSOTG_REG(0x828)
-#define S3C_DVBUSPULSE				S3C_HSOTG_REG(0x82C)
-
-#define S3C_DIEPCTL0				S3C_HSOTG_REG(0x900)
-#define S3C_DOEPCTL0				S3C_HSOTG_REG(0xB00)
-#define S3C_DIEPCTL(_a)				S3C_HSOTG_REG(0x900 + ((_a) * 0x20))
-#define S3C_DOEPCTL(_a)				S3C_HSOTG_REG(0xB00 + ((_a) * 0x20))
-
-/* EP0 specialness:
- * bits[29..28] - reserved (no SetD0PID, SetD1PID)
- * bits[25..22] - should always be zero, this isn't a periodic endpoint
- * bits[10..0] - MPS setting differenct for EP0
-*/
-#define S3C_D0EPCTL_MPS_MASK			(0x3 << 0)
-#define S3C_D0EPCTL_MPS_SHIFT			(0)
-#define S3C_D0EPCTL_MPS_64			(0x0 << 0)
-#define S3C_D0EPCTL_MPS_32			(0x1 << 0)
-#define S3C_D0EPCTL_MPS_16			(0x2 << 0)
-#define S3C_D0EPCTL_MPS_8			(0x3 << 0)
-
-#define S3C_DxEPCTL_EPEna			(1 << 31)
-#define S3C_DxEPCTL_EPDis			(1 << 30)
-#define S3C_DxEPCTL_SetD1PID			(1 << 29)
-#define S3C_DxEPCTL_SetOddFr			(1 << 29)
-#define S3C_DxEPCTL_SetD0PID			(1 << 28)
-#define S3C_DxEPCTL_SetEvenFr			(1 << 28)
-#define S3C_DxEPCTL_SNAK			(1 << 27)
-#define S3C_DxEPCTL_CNAK			(1 << 26)
-#define S3C_DxEPCTL_TxFNum_MASK			(0xf << 22)
-#define S3C_DxEPCTL_TxFNum_SHIFT		(22)
-#define S3C_DxEPCTL_TxFNum_LIMIT		(0xf)
-#define S3C_DxEPCTL_TxFNum(_x)			((_x) << 22)
-
-#define S3C_DxEPCTL_Stall			(1 << 21)
-#define S3C_DxEPCTL_Snp				(1 << 20)
-#define S3C_DxEPCTL_EPType_MASK			(0x3 << 18)
-#define S3C_DxEPCTL_EPType_SHIFT		(18)
-#define S3C_DxEPCTL_EPType_Control		(0x0 << 18)
-#define S3C_DxEPCTL_EPType_Iso			(0x1 << 18)
-#define S3C_DxEPCTL_EPType_Bulk			(0x2 << 18)
-#define S3C_DxEPCTL_EPType_Intterupt		(0x3 << 18)
-
-#define S3C_DxEPCTL_NAKsts			(1 << 17)
-#define S3C_DxEPCTL_DPID			(1 << 16)
-#define S3C_DxEPCTL_EOFrNum			(1 << 16)
-#define S3C_DxEPCTL_USBActEp			(1 << 15)
-#define S3C_DxEPCTL_NextEp_MASK			(0xf << 11)
-#define S3C_DxEPCTL_NextEp_SHIFT		(11)
-#define S3C_DxEPCTL_NextEp_LIMIT		(0xf)
-#define S3C_DxEPCTL_NextEp(_x)			((_x) << 11)
-
-#define S3C_DxEPCTL_MPS_MASK			(0x7ff << 0)
-#define S3C_DxEPCTL_MPS_SHIFT			(0)
-#define S3C_DxEPCTL_MPS_LIMIT			(0x7ff)
-#define S3C_DxEPCTL_MPS(_x)			((_x) << 0)
-
-#define S3C_DIEPINT(_a)				S3C_HSOTG_REG(0x908 + ((_a) * 0x20))
-#define S3C_DOEPINT(_a)				S3C_HSOTG_REG(0xB08 + ((_a) * 0x20))
-
-#define S3C_DxEPINT_INEPNakEff			(1 << 6)
-#define S3C_DxEPINT_Back2BackSetup		(1 << 6)
-#define S3C_DxEPINT_INTknEPMis			(1 << 5)
-#define S3C_DxEPINT_INTknTXFEmp			(1 << 4)
-#define S3C_DxEPINT_OUTTknEPdis			(1 << 4)
-#define S3C_DxEPINT_Timeout			(1 << 3)
-#define S3C_DxEPINT_Setup			(1 << 3)
-#define S3C_DxEPINT_AHBErr			(1 << 2)
-#define S3C_DxEPINT_EPDisbld			(1 << 1)
-#define S3C_DxEPINT_XferCompl			(1 << 0)
-
-#define S3C_DIEPTSIZ0				S3C_HSOTG_REG(0x910)
-
-#define S3C_DIEPTSIZ0_PktCnt_MASK		(0x3 << 19)
-#define S3C_DIEPTSIZ0_PktCnt_SHIFT		(19)
-#define S3C_DIEPTSIZ0_PktCnt_LIMIT		(0x3)
-#define S3C_DIEPTSIZ0_PktCnt(_x)		((_x) << 19)
-
-#define S3C_DIEPTSIZ0_XferSize_MASK		(0x7f << 0)
-#define S3C_DIEPTSIZ0_XferSize_SHIFT		(0)
-#define S3C_DIEPTSIZ0_XferSize_LIMIT		(0x7f)
-#define S3C_DIEPTSIZ0_XferSize(_x)		((_x) << 0)
-
-
-#define DOEPTSIZ0				S3C_HSOTG_REG(0xB10)
-#define S3C_DOEPTSIZ0_SUPCnt_MASK		(0x3 << 29)
-#define S3C_DOEPTSIZ0_SUPCnt_SHIFT		(29)
-#define S3C_DOEPTSIZ0_SUPCnt_LIMIT		(0x3)
-#define S3C_DOEPTSIZ0_SUPCnt(_x)		((_x) << 29)
-
-#define S3C_DOEPTSIZ0_PktCnt			(1 << 19)
-#define S3C_DOEPTSIZ0_XferSize_MASK		(0x7f << 0)
-#define S3C_DOEPTSIZ0_XferSize_SHIFT		(0)
-
-#define S3C_DIEPTSIZ(_a)			S3C_HSOTG_REG(0x910 + ((_a) * 0x20))
-#define S3C_DOEPTSIZ(_a)			S3C_HSOTG_REG(0xB10 + ((_a) * 0x20))
-
-#define S3C_DxEPTSIZ_MC_MASK			(0x3 << 29)
-#define S3C_DxEPTSIZ_MC_SHIFT			(29)
-#define S3C_DxEPTSIZ_MC_LIMIT			(0x3)
-#define S3C_DxEPTSIZ_MC(_x)			((_x) << 29)
-
-#define S3C_DxEPTSIZ_PktCnt_MASK		(0x3ff << 19)
-#define S3C_DxEPTSIZ_PktCnt_SHIFT		(19)
-#define S3C_DxEPTSIZ_PktCnt_GET(_v)		(((_v) >> 19) & 0x3ff)
-#define S3C_DxEPTSIZ_PktCnt_LIMIT		(0x3ff)
-#define S3C_DxEPTSIZ_PktCnt(_x)			((_x) << 19)
-
-#define S3C_DxEPTSIZ_XferSize_MASK		(0x7ffff << 0)
-#define S3C_DxEPTSIZ_XferSize_SHIFT		(0)
-#define S3C_DxEPTSIZ_XferSize_GET(_v)		(((_v) >> 0) & 0x7ffff)
-#define S3C_DxEPTSIZ_XferSize_LIMIT		(0x7ffff)
-#define S3C_DxEPTSIZ_XferSize(_x)		((_x) << 0)
-
-
-#define S3C_DIEPDMA(_a)				S3C_HSOTG_REG(0x914 + ((_a) * 0x20))
-#define S3C_DOEPDMA(_a)				S3C_HSOTG_REG(0xB14 + ((_a) * 0x20))
-#define S3C_DTXFSTS(_a)				S3C_HSOTG_REG(0x918 + ((_a) * 0x20))
-
-#define S3C_EPFIFO(_a)				S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000))
-
-#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_H */
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 6c7945b4cad3..9c5c73aae4f4 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -361,7 +361,6 @@ struct dwc3_ep {
 	dma_addr_t		trb_pool_dma;
 	u32			free_slot;
 	u32			busy_slot;
-	const struct usb_endpoint_descriptor *desc;
 	const struct usb_ss_ep_comp_descriptor *comp_desc;
 	struct dwc3		*dwc;
 
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 3584a169886f..3453ca1f7479 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -179,7 +179,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
 	int				ret;
 
 	spin_lock_irqsave(&dwc->lock, flags);
-	if (!dep->desc) {
+	if (!dep->endpoint.desc) {
 		dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
 				request, dep->name);
 		ret = -ESHUTDOWN;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5255fe975ea1..561625a1284d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -178,8 +178,8 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
 		if (!(dep->flags & DWC3_EP_ENABLED))
 			continue;
 
-		if (usb_endpoint_xfer_bulk(dep->desc)
-				|| usb_endpoint_xfer_isoc(dep->desc))
+		if (usb_endpoint_xfer_bulk(dep->endpoint.desc)
+				|| usb_endpoint_xfer_isoc(dep->endpoint.desc))
 			mult = 3;
 
 		/*
@@ -229,7 +229,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 		 * completed (not the LINK TRB).
 		 */
 		if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
-				usb_endpoint_xfer_isoc(dep->desc))
+				usb_endpoint_xfer_isoc(dep->endpoint.desc))
 			dep->busy_slot++;
 	}
 	list_del(&req->list);
@@ -470,7 +470,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
 		if (ret)
 			return ret;
 
-		dep->desc = desc;
+		dep->endpoint.desc = desc;
 		dep->comp_desc = comp_desc;
 		dep->type = usb_endpoint_type(desc);
 		dep->flags |= DWC3_EP_ENABLED;
@@ -533,7 +533,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 	dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
 
 	dep->stream_capable = false;
-	dep->desc = NULL;
 	dep->endpoint.desc = NULL;
 	dep->comp_desc = NULL;
 	dep->type = 0;
@@ -694,7 +693,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 
 	/* Skip the LINK-TRB on ISOC */
 	if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
-			usb_endpoint_xfer_isoc(dep->desc))
+			usb_endpoint_xfer_isoc(dep->endpoint.desc))
 		return;
 
 	if (!req->trb) {
@@ -707,7 +706,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 	trb->bpl = lower_32_bits(dma);
 	trb->bph = upper_32_bits(dma);
 
-	switch (usb_endpoint_type(dep->desc)) {
+	switch (usb_endpoint_type(dep->endpoint.desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
 		trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP;
 		break;
@@ -732,7 +731,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 		BUG();
 	}
 
-	if (usb_endpoint_xfer_isoc(dep->desc)) {
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 		trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
 		trb->ctrl |= DWC3_TRB_CTRL_CSP;
 	} else {
@@ -743,7 +742,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 			trb->ctrl |= DWC3_TRB_CTRL_LST;
 	}
 
-	if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
+	if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable)
 		trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
 
 	trb->ctrl |= DWC3_TRB_CTRL_HWO;
@@ -771,7 +770,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 	trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK;
 
 	/* Can't wrap around on a non-isoc EP since there's no link TRB */
-	if (!usb_endpoint_xfer_isoc(dep->desc)) {
+	if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 		max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK);
 		if (trbs_left > max)
 			trbs_left = max;
@@ -797,7 +796,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 		 * processed from the first TRB until the last one. Since we
 		 * don't wrap around we have to start at the beginning.
 		 */
-		if (usb_endpoint_xfer_isoc(dep->desc)) {
+		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 			dep->busy_slot = 1;
 			dep->free_slot = 1;
 		} else {
@@ -807,7 +806,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 	}
 
 	/* The last TRB is a link TRB, not used for xfer */
-	if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc))
+	if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc))
 		return;
 
 	list_for_each_entry_safe(req, n, &dep->request_list, list) {
@@ -984,7 +983,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		int start_trans;
 
 		start_trans = 1;
-		if (usb_endpoint_xfer_isoc(dep->desc) &&
+		if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
 				(dep->flags & DWC3_EP_BUSY))
 			start_trans = 0;
 
@@ -1011,7 +1010,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
 
 	int				ret;
 
-	if (!dep->desc) {
+	if (!dep->endpoint.desc) {
 		dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
 				request, ep->name);
 		return -ESHUTDOWN;
@@ -1125,7 +1124,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	if (usb_endpoint_xfer_isoc(dep->desc)) {
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 		dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
 		ret = -EINVAL;
 		goto out;
@@ -1681,7 +1680,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 	case DWC3_DEPEVT_XFERCOMPLETE:
 		dep->res_trans_idx = 0;
 
-		if (usb_endpoint_xfer_isoc(dep->desc)) {
+		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 			dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n",
 					dep->name);
 			return;
@@ -1690,7 +1689,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 		dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
 		break;
 	case DWC3_DEPEVT_XFERINPROGRESS:
-		if (!usb_endpoint_xfer_isoc(dep->desc)) {
+		if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 			dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n",
 					dep->name);
 			return;
@@ -1699,7 +1698,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 		dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
 		break;
 	case DWC3_DEPEVT_XFERNOTREADY:
-		if (usb_endpoint_xfer_isoc(dep->desc)) {
+		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 			dwc3_gadget_start_isoc(dwc, dep, event);
 		} else {
 			int ret;
@@ -1720,7 +1719,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 
 		break;
 	case DWC3_DEPEVT_STREAMEVT:
-		if (!usb_endpoint_xfer_bulk(dep->desc)) {
+		if (!usb_endpoint_xfer_bulk(dep->endpoint.desc)) {
 			dev_err(dwc->dev, "Stream event for non-Bulk %s\n",
 					dep->name);
 			return;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 827697271316..fb883e1405bc 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -172,7 +172,7 @@ config USB_FSL_USB2
 	select USB_GADGET_DUALSPEED
 	select USB_FSL_MPH_DR_OF if OF
 	help
-	   Some of Freescale PowerPC processors have a High Speed
+	   Some of Freescale PowerPC and i.MX processors have a High Speed
 	   Dual-Role(DR) USB controller, which supports device mode.
 
 	   The number of programmable endpoints is different through
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 77779271f487..187d21181cd5 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -333,7 +333,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
 		return -ESHUTDOWN;
 
 	spin_lock_irqsave(&dev->lock, iflags);
-	ep->desc = desc;
+	ep->ep.desc = desc;
 
 	ep->halted = 0;
 
@@ -442,7 +442,6 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
 	u32		tmp;
 
 	VDBG(ep->dev, "ep-%d reset\n", ep->num);
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->ep.ops = &udc_ep_ops;
 	INIT_LIST_HEAD(&ep->queue);
@@ -489,7 +488,7 @@ static int udc_ep_disable(struct usb_ep *usbep)
 		return -EINVAL;
 
 	ep = container_of(usbep, struct udc_ep, ep);
-	if (usbep->name == ep0_string || !ep->desc)
+	if (usbep->name == ep0_string || !ep->ep.desc)
 		return -EINVAL;
 
 	DBG(ep->dev, "Disable ep-%d\n", ep->num);
@@ -1066,7 +1065,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
 		return -EINVAL;
 
 	ep = container_of(usbep, struct udc_ep, ep);
-	if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+	if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
 		return -EINVAL;
 
 	VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in);
@@ -1257,7 +1256,7 @@ static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
 	unsigned long		iflags;
 
 	ep = container_of(usbep, struct udc_ep, ep);
-	if (!usbep || !usbreq || (!ep->desc && (ep->num != 0
+	if (!usbep || !usbreq || (!ep->ep.desc && (ep->num != 0
 				&& ep->num != UDC_EP0OUT_IX)))
 		return -EINVAL;
 
@@ -1317,7 +1316,7 @@ udc_set_halt(struct usb_ep *usbep, int halt)
 	pr_debug("set_halt %s: halt=%d\n", usbep->name, halt);
 
 	ep = container_of(usbep, struct udc_ep, ep);
-	if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+	if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
 		return -EINVAL;
 	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
@@ -1539,7 +1538,7 @@ static void udc_setup_endpoints(struct udc *dev)
 		 * disabling ep interrupts when ENUM interrupt occurs but ep is
 		 * not enabled by gadget driver
 		 */
-		if (!ep->desc)
+		if (!ep->ep.desc)
 			ep_init(dev->regs, ep);
 
 		if (use_dma) {
@@ -3402,19 +3401,7 @@ static struct pci_driver udc_pci_driver = {
 	.remove =	udc_pci_remove,
 };
 
-/* Inits driver */
-static int __init init(void)
-{
-	return pci_register_driver(&udc_pci_driver);
-}
-module_init(init);
-
-/* Cleans driver */
-static void __exit cleanup(void)
-{
-	pci_unregister_driver(&udc_pci_driver);
-}
-module_exit(cleanup);
+module_pci_driver(udc_pci_driver);
 
 MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
 MODULE_AUTHOR("Thomas Dahlmann");
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h
index f87e29c65325..14af87d65caa 100644
--- a/drivers/usb/gadget/amd5536udc.h
+++ b/drivers/usb/gadget/amd5536udc.h
@@ -512,7 +512,6 @@ struct udc_ep {
 
 	/* queue for requests */
 	struct list_head		queue;
-	const struct usb_endpoint_descriptor	*desc;
 	unsigned			halted;
 	unsigned			cancel_transfer;
 	unsigned			num : 5,
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 9d7bcd910074..43943aa965dc 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -212,7 +212,7 @@ static int proc_udc_show(struct seq_file *s, void *unused)
 	if (udc->enabled && udc->vbus) {
 		proc_ep_show(s, &udc->ep[0]);
 		list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
-			if (ep->desc)
+			if (ep->ep.desc)
 				proc_ep_show(s, ep);
 		}
 	}
@@ -530,7 +530,7 @@ ok:
 	tmp |= AT91_UDP_EPEDS;
 	__raw_writel(tmp, ep->creg);
 
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->ep.maxpacket = maxpacket;
 
 	/*
@@ -558,7 +558,6 @@ static int at91_ep_disable (struct usb_ep * _ep)
 	nuke(ep, -ESHUTDOWN);
 
 	/* restore the endpoint's pristine config */
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->ep.maxpacket = ep->maxpacket;
 
@@ -618,7 +617,7 @@ static int at91_ep_queue(struct usb_ep *_ep,
 		return -EINVAL;
 	}
 
-	if (!_ep || (!ep->desc && ep->ep.name != ep0name)) {
+	if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) {
 		DBG("invalid ep\n");
 		return -EINVAL;
 	}
@@ -833,7 +832,7 @@ static void udc_reinit(struct at91_udc *udc)
 
 		if (i != 0)
 			list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
-		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->stopped = 0;
 		ep->fifo_bank = 0;
 		ep->ep.maxpacket = ep->maxpacket;
@@ -978,18 +977,18 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
-static int at91_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *));
-static int at91_stop(struct usb_gadget_driver *driver);
-
+static int at91_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
+static int at91_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
 static const struct usb_gadget_ops at91_udc_ops = {
 	.get_frame		= at91_get_frame,
 	.wakeup			= at91_wakeup,
 	.set_selfpowered	= at91_set_selfpowered,
 	.vbus_session		= at91_vbus_session,
 	.pullup			= at91_pullup,
-	.start			= at91_start,
-	.stop			= at91_stop,
+	.udc_start		= at91_start,
+	.udc_stop		= at91_stop,
 
 	/*
 	 * VBUS-powered devices may also also want to support bigger
@@ -1172,7 +1171,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
 			| USB_REQ_GET_STATUS:
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		ep = &udc->ep[tmp];
-		if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc))
+		if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc))
 			goto stall;
 
 		if (tmp) {
@@ -1197,7 +1196,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
 		ep = &udc->ep[tmp];
 		if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
 			goto stall;
-		if (!ep->desc || ep->is_iso)
+		if (!ep->ep.desc || ep->is_iso)
 			goto stall;
 		if ((w_index & USB_DIR_IN)) {
 			if (!ep->is_in)
@@ -1218,7 +1217,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
 			goto stall;
 		if (tmp == 0)
 			goto succeed;
-		if (!ep->desc || ep->is_iso)
+		if (!ep->ep.desc || ep->is_iso)
 			goto stall;
 		if ((w_index & USB_DIR_IN)) {
 			if (!ep->is_in)
@@ -1627,66 +1626,34 @@ static void at91_vbus_timer(unsigned long data)
 		schedule_work(&udc->vbus_timer_work);
 }
 
-static int at91_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
+static int at91_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct at91_udc	*udc = &controller;
-	int		retval;
-	unsigned long	flags;
-
-	if (!driver
-			|| driver->max_speed < USB_SPEED_FULL
-			|| !bind
-			|| !driver->setup) {
-		DBG("bad parameter.\n");
-		return -EINVAL;
-	}
-
-	if (udc->driver) {
-		DBG("UDC already has a gadget driver\n");
-		return -EBUSY;
-	}
+	struct at91_udc	*udc;
 
+	udc = container_of(gadget, struct at91_udc, gadget);
 	udc->driver = driver;
 	udc->gadget.dev.driver = &driver->driver;
 	dev_set_drvdata(&udc->gadget.dev, &driver->driver);
 	udc->enabled = 1;
 	udc->selfpowered = 1;
 
-	retval = bind(&udc->gadget);
-	if (retval) {
-		DBG("bind() returned %d\n", retval);
-		udc->driver = NULL;
-		udc->gadget.dev.driver = NULL;
-		dev_set_drvdata(&udc->gadget.dev, NULL);
-		udc->enabled = 0;
-		udc->selfpowered = 0;
-		return retval;
-	}
-
-	spin_lock_irqsave(&udc->lock, flags);
-	pullup(udc, 1);
-	spin_unlock_irqrestore(&udc->lock, flags);
-
 	DBG("bound to %s\n", driver->driver.name);
 	return 0;
 }
 
-static int at91_stop(struct usb_gadget_driver *driver)
+static int at91_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct at91_udc *udc = &controller;
+	struct at91_udc *udc;
 	unsigned long	flags;
 
-	if (!driver || driver != udc->driver || !driver->unbind)
-		return -EINVAL;
-
+	udc = container_of(gadget, struct at91_udc, gadget);
 	spin_lock_irqsave(&udc->lock, flags);
 	udc->enabled = 0;
 	at91_udp_write(udc, AT91_UDP_IDR, ~0);
-	pullup(udc, 0);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	driver->unbind(&udc->gadget);
 	udc->gadget.dev.driver = NULL;
 	dev_set_drvdata(&udc->gadget.dev, NULL);
 	udc->driver = NULL;
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 3c0315b86ace..e647d1c2ada4 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -105,9 +105,6 @@ struct at91_ep {
 	unsigned			is_in:1;
 	unsigned			is_iso:1;
 	unsigned			fifo_bank:1;
-
-	const struct usb_endpoint_descriptor
-					*desc;
 };
 
 /*
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 9f98508966d1..e23bf7984aaf 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -599,13 +599,13 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
 
-	if (ep->desc) {
+	if (ep->ep.desc) {
 		spin_unlock_irqrestore(&ep->udc->lock, flags);
 		DBG(DBG_ERR, "ep%d already enabled\n", ep->index);
 		return -EBUSY;
 	}
 
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->ep.maxpacket = maxpacket;
 
 	usba_ep_writel(ep, CFG, ept_cfg);
@@ -647,7 +647,7 @@ static int usba_ep_disable(struct usb_ep *_ep)
 
 	spin_lock_irqsave(&udc->lock, flags);
 
-	if (!ep->desc) {
+	if (!ep->ep.desc) {
 		spin_unlock_irqrestore(&udc->lock, flags);
 		/* REVISIT because this driver disables endpoints in
 		 * reset_all_endpoints() before calling disconnect(),
@@ -658,7 +658,6 @@ static int usba_ep_disable(struct usb_ep *_ep)
 					ep->ep.name);
 		return -EINVAL;
 	}
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 
 	list_splice_init(&ep->queue, &req_list);
@@ -752,7 +751,7 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
 	 */
 	ret = -ESHUTDOWN;
 	spin_lock_irqsave(&udc->lock, flags);
-	if (ep->desc) {
+	if (ep->ep.desc) {
 		if (list_empty(&ep->queue))
 			submit_request(ep, req);
 
@@ -776,7 +775,8 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n",
 			ep->ep.name, req, _req->length);
 
-	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || !ep->desc)
+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN ||
+	    !ep->ep.desc)
 		return -ESHUTDOWN;
 
 	req->submitted = 0;
@@ -792,7 +792,7 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	/* May have received a reset since last time we checked */
 	ret = -ESHUTDOWN;
 	spin_lock_irqsave(&udc->lock, flags);
-	if (ep->desc) {
+	if (ep->ep.desc) {
 		list_add_tail(&req->queue, &ep->queue);
 
 		if ((!ep_is_control(ep) && ep->is_in) ||
@@ -905,7 +905,7 @@ static int usba_ep_set_halt(struct usb_ep *_ep, int value)
 	DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name,
 			value ? "set" : "clear");
 
-	if (!ep->desc) {
+	if (!ep->ep.desc) {
 		DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n",
 				ep->ep.name);
 		return -ENODEV;
@@ -1008,16 +1008,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
 	return 0;
 }
 
-static int atmel_usba_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *));
-static int atmel_usba_stop(struct usb_gadget_driver *driver);
-
+static int atmel_usba_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
+static int atmel_usba_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
 static const struct usb_gadget_ops usba_udc_ops = {
 	.get_frame		= usba_udc_get_frame,
 	.wakeup			= usba_udc_wakeup,
 	.set_selfpowered	= usba_udc_set_selfpowered,
-	.start			= atmel_usba_start,
-	.stop			= atmel_usba_stop,
+	.udc_start		= atmel_usba_start,
+	.udc_stop		= atmel_usba_stop,
 };
 
 static struct usb_endpoint_descriptor usba_ep0_desc = {
@@ -1071,7 +1071,7 @@ static void reset_all_endpoints(struct usba_udc *udc)
 	 * FIXME remove this code ... and retest thoroughly.
 	 */
 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
-		if (ep->desc) {
+		if (ep->ep.desc) {
 			spin_unlock(&udc->lock);
 			usba_ep_disable(&ep->ep);
 			spin_lock(&udc->lock);
@@ -1089,9 +1089,9 @@ static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
 	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
 		u8 bEndpointAddress;
 
-		if (!ep->desc)
+		if (!ep->ep.desc)
 			continue;
-		bEndpointAddress = ep->desc->bEndpointAddress;
+		bEndpointAddress = ep->ep.desc->bEndpointAddress;
 		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
 			continue;
 		if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
@@ -1727,7 +1727,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
 		    usb_speed_string(udc->gadget.speed));
 
 		ep0 = &usba_ep[0];
-		ep0->desc = &usba_ep0_desc;
+		ep0->ep.desc = &usba_ep0_desc;
 		ep0->state = WAIT_FOR_SETUP;
 		usba_ep_writel(ep0, CFG,
 				(USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
@@ -1795,21 +1795,13 @@ out:
 	return IRQ_HANDLED;
 }
 
-static int atmel_usba_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
+static int atmel_usba_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct usba_udc *udc = &the_udc;
+	struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
 	unsigned long flags;
-	int ret;
-
-	if (!udc->pdev)
-		return -ENODEV;
 
 	spin_lock_irqsave(&udc->lock, flags);
-	if (udc->driver) {
-		spin_unlock_irqrestore(&udc->lock, flags);
-		return -EBUSY;
-	}
 
 	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
 	udc->driver = driver;
@@ -1819,13 +1811,6 @@ static int atmel_usba_start(struct usb_gadget_driver *driver,
 	clk_enable(udc->pclk);
 	clk_enable(udc->hclk);
 
-	ret = bind(&udc->gadget);
-	if (ret) {
-		DBG(DBG_ERR, "Could not bind to driver %s: error %d\n",
-			driver->driver.name, ret);
-		goto err_driver_bind;
-	}
-
 	DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
 
 	udc->vbus_prev = 0;
@@ -1842,23 +1827,14 @@ static int atmel_usba_start(struct usb_gadget_driver *driver,
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	return 0;
-
-err_driver_bind:
-	udc->driver = NULL;
-	udc->gadget.dev.driver = NULL;
-	return ret;
 }
 
-static int atmel_usba_stop(struct usb_gadget_driver *driver)
+static int atmel_usba_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct usba_udc *udc = &the_udc;
+	struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
 	unsigned long flags;
 
-	if (!udc->pdev)
-		return -ENODEV;
-	if (driver != udc->driver || !driver->unbind)
-		return -EINVAL;
-
 	if (gpio_is_valid(udc->vbus_pin))
 		disable_irq(gpio_to_irq(udc->vbus_pin));
 
@@ -1871,10 +1847,6 @@ static int atmel_usba_stop(struct usb_gadget_driver *driver)
 	toggle_bias(0);
 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
 
-	if (udc->driver->disconnect)
-		udc->driver->disconnect(&udc->gadget);
-
-	driver->unbind(&udc->gadget);
 	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index 88a2e07a11a8..9791259cbda7 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -280,7 +280,6 @@ struct usba_ep {
 	struct usba_udc				*udc;
 
 	struct list_head			queue;
-	const struct usb_endpoint_descriptor	*desc;
 
 	u16					fifo_size;
 	u8					nr_banks;
diff --git a/drivers/usb/gadget/ci13xxx_pci.c b/drivers/usb/gadget/ci13xxx_pci.c
index 883ab5e832d1..63ef96c04bb7 100644
--- a/drivers/usb/gadget/ci13xxx_pci.c
+++ b/drivers/usb/gadget/ci13xxx_pci.c
@@ -148,27 +148,7 @@ static struct pci_driver ci13xxx_pci_driver = {
 	.remove       =	__devexit_p(ci13xxx_pci_remove),
 };
 
-/**
- * ci13xxx_pci_init: module init
- *
- * Driver load
- */
-static int __init ci13xxx_pci_init(void)
-{
-	return pci_register_driver(&ci13xxx_pci_driver);
-}
-module_init(ci13xxx_pci_init);
-
-/**
- * ci13xxx_pci_exit: module exit
- *
- * Driver unload
- */
-static void __exit ci13xxx_pci_exit(void)
-{
-	pci_unregister_driver(&ci13xxx_pci_driver);
-}
-module_exit(ci13xxx_pci_exit);
+module_pci_driver(ci13xxx_pci_driver);
 
 MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
 MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 3ebc036b1934..1a44bf9c374f 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1916,7 +1916,7 @@ __acquires(udc->lock)
 		int type, num, dir, err = -EINVAL;
 		struct usb_ctrlrequest req;
 
-		if (mEp->desc == NULL)
+		if (mEp->ep.desc == NULL)
 			continue;   /* not configured */
 
 		if (hw_test_and_clear_complete(i)) {
@@ -2112,7 +2112,7 @@ static int ep_enable(struct usb_ep *ep,
 
 	/* only internal SW should enable ctrl endpts */
 
-	mEp->desc = desc;
+	mEp->ep.desc = desc;
 
 	if (!list_empty(&mEp->qh.queue))
 		warn("enabling a non-empty endpoint!");
@@ -2164,7 +2164,7 @@ static int ep_disable(struct usb_ep *ep)
 
 	if (ep == NULL)
 		return -EINVAL;
-	else if (mEp->desc == NULL)
+	else if (mEp->ep.desc == NULL)
 		return -EBUSY;
 
 	spin_lock_irqsave(mEp->lock, flags);
@@ -2183,7 +2183,6 @@ static int ep_disable(struct usb_ep *ep)
 
 	} while (mEp->dir != direction);
 
-	mEp->desc = NULL;
 	mEp->ep.desc = NULL;
 
 	spin_unlock_irqrestore(mEp->lock, flags);
@@ -2272,7 +2271,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 
 	trace("%p, %p, %X", ep, req, gfp_flags);
 
-	if (ep == NULL || req == NULL || mEp->desc == NULL)
+	if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
 		return -EINVAL;
 
 	spin_lock_irqsave(mEp->lock, flags);
@@ -2335,7 +2334,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 	trace("%p, %p", ep, req);
 
 	if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
-		mEp->desc == NULL || list_empty(&mReq->queue) ||
+		mEp->ep.desc == NULL || list_empty(&mReq->queue) ||
 		list_empty(&mEp->qh.queue))
 		return -EINVAL;
 
@@ -2378,7 +2377,7 @@ static int ep_set_halt(struct usb_ep *ep, int value)
 
 	trace("%p, %i", ep, value);
 
-	if (ep == NULL || mEp->desc == NULL)
+	if (ep == NULL || mEp->ep.desc == NULL)
 		return -EINVAL;
 
 	spin_lock_irqsave(mEp->lock, flags);
@@ -2421,7 +2420,7 @@ static int ep_set_wedge(struct usb_ep *ep)
 
 	trace("%p", ep);
 
-	if (ep == NULL || mEp->desc == NULL)
+	if (ep == NULL || mEp->ep.desc == NULL)
 		return -EINVAL;
 
 	spin_lock_irqsave(mEp->lock, flags);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index c4cec6a43d5e..6490cf872adb 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -82,7 +82,6 @@ struct ci13xxx_req {
 /* Extension of usb_ep */
 struct ci13xxx_ep {
 	struct usb_ep                          ep;
-	const struct usb_endpoint_descriptor  *desc;
 	u8                                     dir;
 	u8                                     num;
 	u8                                     type;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index baaebf2830fc..a3b19fe37f53 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -737,6 +737,19 @@ int usb_add_config(struct usb_composite_dev *cdev,
 
 	status = bind(config);
 	if (status < 0) {
+		while (!list_empty(&config->functions)) {
+			struct usb_function		*f;
+
+			f = list_first_entry(&config->functions,
+					struct usb_function, list);
+			list_del(&f->list);
+			if (f->unbind) {
+				DBG(cdev, "unbind function '%s'/%p\n",
+					f->name, f);
+				f->unbind(config, f);
+				/* may free memory for "f" */
+			}
+		}
 		list_del(&config->list);
 		config->cdev = NULL;
 	} else {
@@ -785,7 +798,7 @@ done:
 static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
 {
 	const struct usb_gadget_strings	*s;
-	u16				language;
+	__le16				language;
 	__le16				*tmp;
 
 	while (*sp) {
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 170cbe89d9f8..83bb2e3fa861 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -595,14 +595,12 @@ static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
 
 static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
 {
-	struct dummy_ep		*ep;
 	struct dummy_request	*req;
 
-	if (!_ep || !_req)
-		return;
-	ep = usb_ep_to_dummy_ep(_ep);
-	if (!ep->desc && _ep->name != ep0name)
+	if (!_ep || !_req) {
+		__WARN();
 		return;
+	}
 
 	req = usb_request_to_dummy_request(_req);
 	WARN_ON(!list_empty(&req->queue));
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index f52cb1ae45d9..1d4c535671a7 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1473,8 +1473,22 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev,
 
 static void ffs_func_free(struct ffs_function *func)
 {
+	struct ffs_ep *ep         = func->eps;
+	unsigned count            = func->ffs->eps_count;
+	unsigned long flags;
+
 	ENTER();
 
+	/* cleanup after autoconfig */
+	spin_lock_irqsave(&func->ffs->eps_lock, flags);
+	do {
+		if (ep->ep && ep->req)
+			usb_ep_free_request(ep->ep, ep->req);
+		ep->req = NULL;
+		++ep;
+	} while (--count);
+	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+
 	ffs_data_put(func->ffs);
 
 	kfree(func->eps);
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 2c0cd824c667..7275706caeb0 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -286,7 +286,7 @@ static void disable_loopback(struct f_loopback *loop)
 	struct usb_composite_dev	*cdev;
 
 	cdev = loop->function.config->cdev;
-	disable_endpoints(cdev, loop->in_ep, loop->out_ep);
+	disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
 	VDBG(cdev, "%s disabled\n", loop->function.name);
 }
 
@@ -329,7 +329,7 @@ fail0:
 	 * than 'buflen' bytes each.
 	 */
 	for (i = 0; i < qlen && result == 0; i++) {
-		req = alloc_ep_req(ep);
+		req = alloc_ep_req(ep, 0);
 		if (req) {
 			req->complete = loopback_complete;
 			result = usb_ep_queue(ep, req, GFP_ATOMIC);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index cb8c162cae5a..f67b453740bd 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -3110,13 +3110,6 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,
 	return rc;
 }
 
-static inline int __deprecated __maybe_unused
-fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c,
-	struct fsg_common *common)
-{
-	return fsg_bind_config(cdev, c, common);
-}
-
 
 /************************* Module parameters *************************/
 
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 7aa7ac82c02c..5c1b68b63c98 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -51,6 +51,9 @@ struct f_sourcesink {
 
 	struct usb_ep		*in_ep;
 	struct usb_ep		*out_ep;
+	struct usb_ep		*iso_in_ep;
+	struct usb_ep		*iso_out_ep;
+	int			cur_alt;
 };
 
 static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@@ -59,18 +62,45 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
 }
 
 static unsigned pattern;
-module_param(pattern, uint, 0);
-MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
+module_param(pattern, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none");
+
+static unsigned isoc_interval = 4;
+module_param(isoc_interval, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_interval, "1 - 16");
+
+static unsigned isoc_maxpacket = 1024;
+module_param(isoc_maxpacket, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+
+static unsigned isoc_mult;
+module_param(isoc_mult, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
+
+static unsigned isoc_maxburst;
+module_param(isoc_maxburst, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
 
 /*-------------------------------------------------------------------------*/
 
-static struct usb_interface_descriptor source_sink_intf = {
-	.bLength =		sizeof source_sink_intf,
+static struct usb_interface_descriptor source_sink_intf_alt0 = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
+	.bAlternateSetting =	0,
 	.bNumEndpoints =	2,
 	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	/* .iInterface = DYNAMIC */
+	/* .iInterface		= DYNAMIC */
+};
+
+static struct usb_interface_descriptor source_sink_intf_alt1 = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bAlternateSetting =	1,
+	.bNumEndpoints =	4,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	/* .iInterface		= DYNAMIC */
 };
 
 /* full speed support: */
@@ -91,10 +121,36 @@ static struct usb_endpoint_descriptor fs_sink_desc = {
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
+static struct usb_endpoint_descriptor fs_iso_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize =	cpu_to_le16(1023),
+	.bInterval =		4,
+};
+
+static struct usb_endpoint_descriptor fs_iso_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize =	cpu_to_le16(1023),
+	.bInterval =		4,
+};
+
 static struct usb_descriptor_header *fs_source_sink_descs[] = {
-	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &source_sink_intf_alt0,
 	(struct usb_descriptor_header *) &fs_sink_desc,
 	(struct usb_descriptor_header *) &fs_source_desc,
+	(struct usb_descriptor_header *) &source_sink_intf_alt1,
+#define FS_ALT_IFC_1_OFFSET	3
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	(struct usb_descriptor_header *) &fs_iso_sink_desc,
+	(struct usb_descriptor_header *) &fs_iso_source_desc,
 	NULL,
 };
 
@@ -116,10 +172,34 @@ static struct usb_endpoint_descriptor hs_sink_desc = {
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
+static struct usb_endpoint_descriptor hs_iso_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+	.bInterval =		4,
+};
+
+static struct usb_endpoint_descriptor hs_iso_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+	.bInterval =		4,
+};
+
 static struct usb_descriptor_header *hs_source_sink_descs[] = {
-	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &source_sink_intf_alt0,
 	(struct usb_descriptor_header *) &hs_source_desc,
 	(struct usb_descriptor_header *) &hs_sink_desc,
+	(struct usb_descriptor_header *) &source_sink_intf_alt1,
+#define HS_ALT_IFC_1_OFFSET	3
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	(struct usb_descriptor_header *) &hs_iso_source_desc,
+	(struct usb_descriptor_header *) &hs_iso_sink_desc,
 	NULL,
 };
 
@@ -136,6 +216,7 @@ static struct usb_endpoint_descriptor ss_source_desc = {
 struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
 	.bMaxBurst =		0,
 	.bmAttributes =		0,
 	.wBytesPerInterval =	0,
@@ -152,17 +233,64 @@ static struct usb_endpoint_descriptor ss_sink_desc = {
 struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
 	.bLength =		USB_DT_SS_EP_COMP_SIZE,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
 	.bMaxBurst =		0,
 	.bmAttributes =		0,
 	.wBytesPerInterval =	0,
 };
 
+static struct usb_endpoint_descriptor ss_iso_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+	.bInterval =		4,
+};
+
+struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
+	.bLength =		USB_DT_SS_EP_COMP_SIZE,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	.bMaxBurst =		0,
+	.bmAttributes =		0,
+	.wBytesPerInterval =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor ss_iso_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+	.bInterval =		4,
+};
+
+struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
+	.bLength =		USB_DT_SS_EP_COMP_SIZE,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	.bMaxBurst =		0,
+	.bmAttributes =		0,
+	.wBytesPerInterval =	cpu_to_le16(1024),
+};
+
 static struct usb_descriptor_header *ss_source_sink_descs[] = {
-	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &source_sink_intf_alt0,
 	(struct usb_descriptor_header *) &ss_source_desc,
 	(struct usb_descriptor_header *) &ss_source_comp_desc,
 	(struct usb_descriptor_header *) &ss_sink_desc,
 	(struct usb_descriptor_header *) &ss_sink_comp_desc,
+	(struct usb_descriptor_header *) &source_sink_intf_alt1,
+#define SS_ALT_IFC_1_OFFSET	5
+	(struct usb_descriptor_header *) &ss_source_desc,
+	(struct usb_descriptor_header *) &ss_source_comp_desc,
+	(struct usb_descriptor_header *) &ss_sink_desc,
+	(struct usb_descriptor_header *) &ss_sink_comp_desc,
+	(struct usb_descriptor_header *) &ss_iso_source_desc,
+	(struct usb_descriptor_header *) &ss_iso_source_comp_desc,
+	(struct usb_descriptor_header *) &ss_iso_sink_desc,
+	(struct usb_descriptor_header *) &ss_iso_sink_comp_desc,
 	NULL,
 };
 
@@ -196,9 +324,10 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
 	id = usb_interface_id(c, f);
 	if (id < 0)
 		return id;
-	source_sink_intf.bInterfaceNumber = id;
+	source_sink_intf_alt0.bInterfaceNumber = id;
+	source_sink_intf_alt1.bInterfaceNumber = id;
 
-	/* allocate endpoints */
+	/* allocate bulk endpoints */
 	ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
 	if (!ss->in_ep) {
 autoconf_fail:
@@ -213,12 +342,74 @@ autoconf_fail:
 		goto autoconf_fail;
 	ss->out_ep->driver_data = cdev;	/* claim */
 
+	/* sanity check the isoc module parameters */
+	if (isoc_interval < 1)
+		isoc_interval = 1;
+	if (isoc_interval > 16)
+		isoc_interval = 16;
+	if (isoc_mult > 2)
+		isoc_mult = 2;
+	if (isoc_maxburst > 15)
+		isoc_maxburst = 15;
+
+	/* fill in the FS isoc descriptors from the module parameters */
+	fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
+						1023 : isoc_maxpacket;
+	fs_iso_source_desc.bInterval = isoc_interval;
+	fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
+						1023 : isoc_maxpacket;
+	fs_iso_sink_desc.bInterval = isoc_interval;
+
+	/* allocate iso endpoints */
+	ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc);
+	if (!ss->iso_in_ep)
+		goto no_iso;
+	ss->iso_in_ep->driver_data = cdev;	/* claim */
+
+	ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc);
+	if (ss->iso_out_ep) {
+		ss->iso_out_ep->driver_data = cdev;	/* claim */
+	} else {
+		ss->iso_in_ep->driver_data = NULL;
+		ss->iso_in_ep = NULL;
+no_iso:
+		/*
+		 * We still want to work even if the UDC doesn't have isoc
+		 * endpoints, so null out the alt interface that contains
+		 * them and continue.
+		 */
+		fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL;
+		hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL;
+		ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
+	}
+
+	if (isoc_maxpacket > 1024)
+		isoc_maxpacket = 1024;
+
 	/* support high speed hardware */
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
 		hs_source_desc.bEndpointAddress =
 				fs_source_desc.bEndpointAddress;
 		hs_sink_desc.bEndpointAddress =
 				fs_sink_desc.bEndpointAddress;
+
+		/*
+		 * Fill in the HS isoc descriptors from the module parameters.
+		 * We assume that the user knows what they are doing and won't
+		 * give parameters that their UDC doesn't support.
+		 */
+		hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+		hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
+		hs_iso_source_desc.bInterval = isoc_interval;
+		hs_iso_source_desc.bEndpointAddress =
+				fs_iso_source_desc.bEndpointAddress;
+
+		hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+		hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
+		hs_iso_sink_desc.bInterval = isoc_interval;
+		hs_iso_sink_desc.bEndpointAddress =
+				fs_iso_sink_desc.bEndpointAddress;
+
 		f->hs_descriptors = hs_source_sink_descs;
 	}
 
@@ -228,13 +419,39 @@ autoconf_fail:
 				fs_source_desc.bEndpointAddress;
 		ss_sink_desc.bEndpointAddress =
 				fs_sink_desc.bEndpointAddress;
+
+		/*
+		 * Fill in the SS isoc descriptors from the module parameters.
+		 * We assume that the user knows what they are doing and won't
+		 * give parameters that their UDC doesn't support.
+		 */
+		ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+		ss_iso_source_desc.bInterval = isoc_interval;
+		ss_iso_source_comp_desc.bmAttributes = isoc_mult;
+		ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
+		ss_iso_source_comp_desc.wBytesPerInterval =
+			isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+		ss_iso_source_desc.bEndpointAddress =
+				fs_iso_source_desc.bEndpointAddress;
+
+		ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+		ss_iso_sink_desc.bInterval = isoc_interval;
+		ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
+		ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
+		ss_iso_sink_comp_desc.wBytesPerInterval =
+			isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+		ss_iso_sink_desc.bEndpointAddress =
+				fs_iso_sink_desc.bEndpointAddress;
+
 		f->ss_descriptors = ss_source_sink_descs;
 	}
 
-	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+	DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
 	    (gadget_is_superspeed(c->cdev->gadget) ? "super" :
 	     (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
-			f->name, ss->in_ep->name, ss->out_ep->name);
+			f->name, ss->in_ep->name, ss->out_ep->name,
+			ss->iso_in_ep ? ss->iso_in_ep->name : "<none>",
+			ss->iso_out_ep ? ss->iso_out_ep->name : "<none>");
 	return 0;
 }
 
@@ -251,6 +468,9 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
 	u8			*buf = req->buf;
 	struct usb_composite_dev *cdev = ss->function.config->cdev;
 
+	if (pattern == 2)
+		return 0;
+
 	for (i = 0; i < req->actual; i++, buf++) {
 		switch (pattern) {
 
@@ -265,7 +485,7 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
 		 * each usb transfer request should be.  Resync is done
 		 * with set_interface or set_config.  (We *WANT* it to
 		 * get quickly out of sync if controllers or their drivers
-		 * stutter for any reason, including buffer duplcation...)
+		 * stutter for any reason, including buffer duplication...)
 		 */
 		case 1:
 			if (*buf == (u8)(i % 63))
@@ -292,21 +512,30 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
 		for  (i = 0; i < req->length; i++)
 			*buf++ = (u8) (i % 63);
 		break;
+	case 2:
+		break;
 	}
 }
 
 static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
 {
-	struct f_sourcesink	*ss = ep->driver_data;
-	struct usb_composite_dev *cdev = ss->function.config->cdev;
-	int			status = req->status;
+	struct usb_composite_dev	*cdev;
+	struct f_sourcesink		*ss = ep->driver_data;
+	int				status = req->status;
+
+	/* driver_data will be null if ep has been disabled */
+	if (!ss)
+		return;
+
+	cdev = ss->function.config->cdev;
 
 	switch (status) {
 
 	case 0:				/* normal completion? */
 		if (ep == ss->out_ep) {
 			check_read_data(ss, req);
-			memset(req->buf, 0x55, req->length);
+			if (pattern != 2)
+				memset(req->buf, 0x55, req->length);
 		} else
 			reinit_write_data(ep, req);
 		break;
@@ -344,32 +573,57 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
 	}
 }
 
-static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in)
+static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
+		bool is_iso, int speed)
 {
 	struct usb_ep		*ep;
 	struct usb_request	*req;
-	int			status;
+	int			i, size, status;
 
-	ep = is_in ? ss->in_ep : ss->out_ep;
-	req = alloc_ep_req(ep);
-	if (!req)
-		return -ENOMEM;
+	for (i = 0; i < 8; i++) {
+		if (is_iso) {
+			switch (speed) {
+			case USB_SPEED_SUPER:
+				size = isoc_maxpacket * (isoc_mult + 1) *
+						(isoc_maxburst + 1);
+				break;
+			case USB_SPEED_HIGH:
+				size = isoc_maxpacket * (isoc_mult + 1);
+				break;
+			default:
+				size = isoc_maxpacket > 1023 ?
+						1023 : isoc_maxpacket;
+				break;
+			}
+			ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
+			req = alloc_ep_req(ep, size);
+		} else {
+			ep = is_in ? ss->in_ep : ss->out_ep;
+			req = alloc_ep_req(ep, 0);
+		}
 
-	req->complete = source_sink_complete;
-	if (is_in)
-		reinit_write_data(ep, req);
-	else
-		memset(req->buf, 0x55, req->length);
+		if (!req)
+			return -ENOMEM;
 
-	status = usb_ep_queue(ep, req, GFP_ATOMIC);
-	if (status) {
-		struct usb_composite_dev	*cdev;
+		req->complete = source_sink_complete;
+		if (is_in)
+			reinit_write_data(ep, req);
+		else if (pattern != 2)
+			memset(req->buf, 0x55, req->length);
 
-		cdev = ss->function.config->cdev;
-		ERROR(cdev, "start %s %s --> %d\n",
-				is_in ? "IN" : "OUT",
-				ep->name, status);
-		free_ep_req(ep, req);
+		status = usb_ep_queue(ep, req, GFP_ATOMIC);
+		if (status) {
+			struct usb_composite_dev	*cdev;
+
+			cdev = ss->function.config->cdev;
+			ERROR(cdev, "start %s%s %s --> %d\n",
+			      is_iso ? "ISO-" : "", is_in ? "IN" : "OUT",
+			      ep->name, status);
+			free_ep_req(ep, req);
+		}
+
+		if (!is_iso)
+			break;
 	}
 
 	return status;
@@ -380,17 +634,20 @@ static void disable_source_sink(struct f_sourcesink *ss)
 	struct usb_composite_dev	*cdev;
 
 	cdev = ss->function.config->cdev;
-	disable_endpoints(cdev, ss->in_ep, ss->out_ep);
+	disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep,
+			ss->iso_out_ep);
 	VDBG(cdev, "%s disabled\n", ss->function.name);
 }
 
 static int
-enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
+enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
+		int alt)
 {
 	int					result = 0;
+	int					speed = cdev->gadget->speed;
 	struct usb_ep				*ep;
 
-	/* one endpoint writes (sources) zeroes IN (to the host) */
+	/* one bulk endpoint writes (sources) zeroes IN (to the host) */
 	ep = ss->in_ep;
 	result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
 	if (result)
@@ -400,7 +657,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
 		return result;
 	ep->driver_data = ss;
 
-	result = source_sink_start_ep(ss, true);
+	result = source_sink_start_ep(ss, true, false, speed);
 	if (result < 0) {
 fail:
 		ep = ss->in_ep;
@@ -409,7 +666,7 @@ fail:
 		return result;
 	}
 
-	/* one endpoint reads (sinks) anything OUT (from the host) */
+	/* one bulk endpoint reads (sinks) anything OUT (from the host) */
 	ep = ss->out_ep;
 	result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
 	if (result)
@@ -419,27 +676,82 @@ fail:
 		goto fail;
 	ep->driver_data = ss;
 
-	result = source_sink_start_ep(ss, false);
+	result = source_sink_start_ep(ss, false, false, speed);
 	if (result < 0) {
+fail2:
+		ep = ss->out_ep;
 		usb_ep_disable(ep);
 		ep->driver_data = NULL;
 		goto fail;
 	}
 
-	DBG(cdev, "%s enabled\n", ss->function.name);
+	if (alt == 0)
+		goto out;
+
+	/* one iso endpoint writes (sources) zeroes IN (to the host) */
+	ep = ss->iso_in_ep;
+	if (ep) {
+		result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+		if (result)
+			goto fail2;
+		result = usb_ep_enable(ep);
+		if (result < 0)
+			goto fail2;
+		ep->driver_data = ss;
+
+		result = source_sink_start_ep(ss, true, true, speed);
+		if (result < 0) {
+fail3:
+			ep = ss->iso_in_ep;
+			if (ep) {
+				usb_ep_disable(ep);
+				ep->driver_data = NULL;
+			}
+			goto fail2;
+		}
+	}
+
+	/* one iso endpoint reads (sinks) anything OUT (from the host) */
+	ep = ss->iso_out_ep;
+	if (ep) {
+		result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+		if (result)
+			goto fail3;
+		result = usb_ep_enable(ep);
+		if (result < 0)
+			goto fail3;
+		ep->driver_data = ss;
+
+		result = source_sink_start_ep(ss, false, true, speed);
+		if (result < 0) {
+			usb_ep_disable(ep);
+			ep->driver_data = NULL;
+			goto fail3;
+		}
+	}
+out:
+	ss->cur_alt = alt;
+
+	DBG(cdev, "%s enabled, alt intf %d\n", ss->function.name, alt);
 	return result;
 }
 
 static int sourcesink_set_alt(struct usb_function *f,
 		unsigned intf, unsigned alt)
 {
-	struct f_sourcesink	*ss = func_to_ss(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
+	struct f_sourcesink		*ss = func_to_ss(f);
+	struct usb_composite_dev	*cdev = f->config->cdev;
 
-	/* we know alt is zero */
 	if (ss->in_ep->driver_data)
 		disable_source_sink(ss);
-	return enable_source_sink(cdev, ss);
+	return enable_source_sink(cdev, ss, alt);
+}
+
+static int sourcesink_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_sourcesink		*ss = func_to_ss(f);
+
+	return ss->cur_alt;
 }
 
 static void sourcesink_disable(struct usb_function *f)
@@ -465,6 +777,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
 	ss->function.bind = sourcesink_bind;
 	ss->function.unbind = sourcesink_unbind;
 	ss->function.set_alt = sourcesink_set_alt;
+	ss->function.get_alt = sourcesink_get_alt;
 	ss->function.disable = sourcesink_disable;
 
 	status = usb_add_function(c, &ss->function);
@@ -536,7 +849,7 @@ unknown:
 		req->length = value;
 		value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0)
-			ERROR(c->cdev, "source/sinkc response, err %d\n",
+			ERROR(c->cdev, "source/sink response, err %d\n",
 					value);
 	}
 
@@ -545,12 +858,12 @@ unknown:
 }
 
 static struct usb_configuration sourcesink_driver = {
-	.label		= "source/sink",
-	.strings	= sourcesink_strings,
-	.setup		= sourcesink_setup,
-	.bConfigurationValue = 3,
-	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
-	/* .iConfiguration = DYNAMIC */
+	.label			= "source/sink",
+	.strings		= sourcesink_strings,
+	.setup			= sourcesink_setup,
+	.bConfigurationValue	= 3,
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	/* .iConfiguration	= DYNAMIC */
 };
 
 /**
@@ -567,7 +880,8 @@ int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
 		return id;
 	strings_sourcesink[0].id = id;
 
-	source_sink_intf.iInterface = id;
+	source_sink_intf_alt0.iInterface = id;
+	source_sink_intf_alt1.iInterface = id;
 	sourcesink_driver.iConfiguration = id;
 
 	/* support autoresume for remote wakeup testing */
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 877a2c46672b..51881f3bd07a 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -71,9 +71,6 @@ static struct usb_endpoint_descriptor qe_ep0_desc = {
 	.wMaxPacketSize =	USB_MAX_CTRL_PAYLOAD,
 };
 
-/* it is initialized in probe()  */
-static struct qe_udc *udc_controller;
-
 /********************************************************************
  *      Internal Used Function Start
 ********************************************************************/
@@ -188,8 +185,8 @@ static int qe_ep0_stall(struct qe_udc *udc)
 {
 	qe_eptx_stall_change(&udc->eps[0], 1);
 	qe_eprx_stall_change(&udc->eps[0], 1);
-	udc_controller->ep0_state = WAIT_FOR_SETUP;
-	udc_controller->ep0_dir = 0;
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->ep0_dir = 0;
 	return 0;
 }
 
@@ -450,13 +447,13 @@ static int qe_ep_rxbd_update(struct qe_ep *ep)
 
 	ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer);
 	if (ep->rxbuf_d == DMA_ADDR_INVALID) {
-		ep->rxbuf_d = dma_map_single(udc_controller->gadget.dev.parent,
+		ep->rxbuf_d = dma_map_single(ep->udc->gadget.dev.parent,
 					ep->rxbuffer,
 					size,
 					DMA_FROM_DEVICE);
 		ep->rxbufmap = 1;
 	} else {
-		dma_sync_single_for_device(udc_controller->gadget.dev.parent,
+		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
 					ep->rxbuf_d, size,
 					DMA_FROM_DEVICE);
 		ep->rxbufmap = 0;
@@ -489,10 +486,10 @@ static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
 	epparam = udc->ep_param[pipe_num];
 
 	usep = 0;
-	logepnum = (ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	logepnum = (ep->ep.desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 	usep |= (logepnum << USB_EPNUM_SHIFT);
 
-	switch (ep->desc->bmAttributes & 0x03) {
+	switch (ep->ep.desc->bmAttributes & 0x03) {
 	case USB_ENDPOINT_XFER_BULK:
 		usep |= USB_TRANS_BULK;
 		break;
@@ -644,7 +641,7 @@ static int qe_ep_init(struct qe_udc *udc,
 	/* initialize ep structure */
 	ep->ep.maxpacket = max;
 	ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->stopped = 0;
 	ep->init = 1;
 
@@ -698,14 +695,14 @@ en_done:
 	return -ENODEV;
 }
 
-static inline void qe_usb_enable(void)
+static inline void qe_usb_enable(struct qe_udc *udc)
 {
-	setbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
+	setbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
 }
 
-static inline void qe_usb_disable(void)
+static inline void qe_usb_disable(struct qe_udc *udc)
 {
-	clrbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
+	clrbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN);
 }
 
 /*----------------------------------------------------------------------------*
@@ -1599,7 +1596,7 @@ static int qe_ep_enable(struct usb_ep *_ep,
 	ep = container_of(_ep, struct qe_ep, ep);
 
 	/* catch various bogus parameters */
-	if (!_ep || !desc || ep->desc || _ep->name == ep_name[0] ||
+	if (!_ep || !desc || ep->ep.desc || _ep->name == ep_name[0] ||
 			(desc->bDescriptorType != USB_DT_ENDPOINT))
 		return -EINVAL;
 
@@ -1629,7 +1626,7 @@ static int qe_ep_disable(struct usb_ep *_ep)
 	ep = container_of(_ep, struct qe_ep, ep);
 	udc = ep->udc;
 
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL);
 		return -EINVAL;
 	}
@@ -1637,7 +1634,6 @@ static int qe_ep_disable(struct usb_ep *_ep)
 	spin_lock_irqsave(&udc->lock, flags);
 	/* Nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->tx_req = NULL;
@@ -1656,13 +1652,13 @@ static int qe_ep_disable(struct usb_ep *_ep)
 	if (ep->dir != USB_DIR_IN) {
 		kfree(ep->rxframe);
 		if (ep->rxbufmap) {
-			dma_unmap_single(udc_controller->gadget.dev.parent,
+			dma_unmap_single(udc->gadget.dev.parent,
 					ep->rxbuf_d, size,
 					DMA_FROM_DEVICE);
 			ep->rxbuf_d = DMA_ADDR_INVALID;
 		} else {
 			dma_sync_single_for_cpu(
-					udc_controller->gadget.dev.parent,
+					udc->gadget.dev.parent,
 					ep->rxbuf_d, size,
 					DMA_FROM_DEVICE);
 		}
@@ -1715,7 +1711,7 @@ static int __qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req)
 		dev_dbg(udc->dev, "bad params\n");
 		return -EINVAL;
 	}
-	if (!_ep || (!ep->desc && ep_index(ep))) {
+	if (!_ep || (!ep->ep.desc && ep_index(ep))) {
 		dev_dbg(udc->dev, "bad ep\n");
 		return -EINVAL;
 	}
@@ -1826,7 +1822,7 @@ static int qe_ep_set_halt(struct usb_ep *_ep, int value)
 	struct qe_udc *udc;
 
 	ep = container_of(_ep, struct qe_ep, ep);
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		status = -EINVAL;
 		goto out;
 	}
@@ -1880,9 +1876,10 @@ static struct usb_ep_ops qe_ep_ops = {
 /* Get the current frame number */
 static int qe_get_frame(struct usb_gadget *gadget)
 {
+	struct qe_udc *udc = container_of(gadget, struct qe_udc, gadget);
 	u16 tmp;
 
-	tmp = in_be16(&udc_controller->usb_param->frame_n);
+	tmp = in_be16(&udc->usb_param->frame_n);
 	if (tmp & 0x8000)
 		tmp = tmp & 0x07ff;
 	else
@@ -1891,57 +1888,16 @@ static int qe_get_frame(struct usb_gadget *gadget)
 	return (int)tmp;
 }
 
-/* Tries to wake up the host connected to this gadget
- *
- * Return : 0-success
- * Negative-this feature not enabled by host or not supported by device hw
- */
-static int qe_wakeup(struct usb_gadget *gadget)
-{
-	return -ENOTSUPP;
-}
-
-/* Notify controller that VBUS is powered, Called by whatever
-   detects VBUS sessions */
-static int qe_vbus_session(struct usb_gadget *gadget, int is_active)
-{
-	return -ENOTSUPP;
-}
-
-/* constrain controller's VBUS power usage
- * This call is used by gadget drivers during SET_CONFIGURATION calls,
- * reporting how much power the device may consume.  For example, this
- * could affect how quickly batteries are recharged.
- *
- * Returns zero on success, else negative errno.
- */
-static int qe_vbus_draw(struct usb_gadget *gadget, unsigned mA)
-{
-	return -ENOTSUPP;
-}
-
-/* Change Data+ pullup status
- * this func is used by usb_gadget_connect/disconnect
- */
-static int qe_pullup(struct usb_gadget *gadget, int is_on)
-{
-	return -ENOTSUPP;
-}
-
-static int fsl_qe_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *));
-static int fsl_qe_stop(struct usb_gadget_driver *driver);
+static int fsl_qe_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
+static int fsl_qe_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
 
 /* defined in usb_gadget.h */
 static struct usb_gadget_ops qe_gadget_ops = {
 	.get_frame = qe_get_frame,
-	.wakeup = qe_wakeup,
-/*	.set_selfpowered = qe_set_selfpowered,*/ /* always selfpowered */
-	.vbus_session = qe_vbus_session,
-	.vbus_draw = qe_vbus_draw,
-	.pullup = qe_pullup,
-	.start = fsl_qe_start,
-	.stop = fsl_qe_stop,
+	.udc_start = fsl_qe_start,
+	.udc_stop = fsl_qe_stop,
 };
 
 /*-------------------------------------------------------------------------
@@ -2015,7 +1971,7 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
 		u16 usep;
 
 		/* stall if endpoint doesn't exist */
-		if (!target_ep->desc)
+		if (!target_ep->ep.desc)
 			goto stall;
 
 		usep = in_be16(&udc->usb_regs->usb_usep[pipe]);
@@ -2190,7 +2146,7 @@ static int reset_irq(struct qe_udc *udc)
 	if (udc->usb_state == USB_STATE_DEFAULT)
 		return 0;
 
-	qe_usb_disable();
+	qe_usb_disable(udc);
 	out_8(&udc->usb_regs->usb_usadr, 0);
 
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
@@ -2202,7 +2158,7 @@ static int reset_irq(struct qe_udc *udc)
 	udc->usb_state = USB_STATE_DEFAULT;
 	udc->ep0_state = WAIT_FOR_SETUP;
 	udc->ep0_dir = USB_DIR_OUT;
-	qe_usb_enable();
+	qe_usb_enable(udc);
 	return 0;
 }
 
@@ -2327,92 +2283,65 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc)
 /*-------------------------------------------------------------------------
 	Gadget driver probe and unregister.
  --------------------------------------------------------------------------*/
-static int fsl_qe_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
+static int fsl_qe_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	int retval;
-	unsigned long flags = 0;
-
-	/* standard operations */
-	if (!udc_controller)
-		return -ENODEV;
-
-	if (!driver || driver->max_speed < USB_SPEED_FULL
-			|| !bind || !driver->disconnect || !driver->setup)
-		return -EINVAL;
-
-	if (udc_controller->driver)
-		return -EBUSY;
+	struct qe_udc *udc;
+	unsigned long flags;
 
+	udc = container_of(gadget, struct qe_udc, gadget);
 	/* lock is needed but whether should use this lock or another */
-	spin_lock_irqsave(&udc_controller->lock, flags);
+	spin_lock_irqsave(&udc->lock, flags);
 
 	driver->driver.bus = NULL;
 	/* hook up the driver */
-	udc_controller->driver = driver;
-	udc_controller->gadget.dev.driver = &driver->driver;
-	udc_controller->gadget.speed = driver->max_speed;
-	spin_unlock_irqrestore(&udc_controller->lock, flags);
-
-	retval = bind(&udc_controller->gadget);
-	if (retval) {
-		dev_err(udc_controller->dev, "bind to %s --> %d",
-				driver->driver.name, retval);
-		udc_controller->gadget.dev.driver = NULL;
-		udc_controller->driver = NULL;
-		return retval;
-	}
+	udc->driver = driver;
+	udc->gadget.dev.driver = &driver->driver;
+	udc->gadget.speed = driver->max_speed;
 
 	/* Enable IRQ reg and Set usbcmd reg EN bit */
-	qe_usb_enable();
+	qe_usb_enable(udc);
 
-	out_be16(&udc_controller->usb_regs->usb_usber, 0xffff);
-	out_be16(&udc_controller->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
-	udc_controller->usb_state = USB_STATE_ATTACHED;
-	udc_controller->ep0_state = WAIT_FOR_SETUP;
-	udc_controller->ep0_dir = USB_DIR_OUT;
-	dev_info(udc_controller->dev, "%s bind to driver %s \n",
-		udc_controller->gadget.name, driver->driver.name);
+	out_be16(&udc->usb_regs->usb_usber, 0xffff);
+	out_be16(&udc->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
+	udc->usb_state = USB_STATE_ATTACHED;
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->ep0_dir = USB_DIR_OUT;
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	dev_info(udc->dev, "%s bind to driver %s\n", udc->gadget.name,
+			driver->driver.name);
 	return 0;
 }
 
-static int fsl_qe_stop(struct usb_gadget_driver *driver)
+static int fsl_qe_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
+	struct qe_udc *udc;
 	struct qe_ep *loop_ep;
 	unsigned long flags;
 
-	if (!udc_controller)
-		return -ENODEV;
-
-	if (!driver || driver != udc_controller->driver)
-		return -EINVAL;
-
+	udc = container_of(gadget, struct qe_udc, gadget);
 	/* stop usb controller, disable intr */
-	qe_usb_disable();
+	qe_usb_disable(udc);
 
 	/* in fact, no needed */
-	udc_controller->usb_state = USB_STATE_ATTACHED;
-	udc_controller->ep0_state = WAIT_FOR_SETUP;
-	udc_controller->ep0_dir = 0;
+	udc->usb_state = USB_STATE_ATTACHED;
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->ep0_dir = 0;
 
 	/* stand operation */
-	spin_lock_irqsave(&udc_controller->lock, flags);
-	udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
-	nuke(&udc_controller->eps[0], -ESHUTDOWN);
-	list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list,
-				ep.ep_list)
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	nuke(&udc->eps[0], -ESHUTDOWN);
+	list_for_each_entry(loop_ep, &udc->gadget.ep_list, ep.ep_list)
 		nuke(loop_ep, -ESHUTDOWN);
-	spin_unlock_irqrestore(&udc_controller->lock, flags);
+	spin_unlock_irqrestore(&udc->lock, flags);
 
-	/* report disconnect; the controller is already quiesced */
-	driver->disconnect(&udc_controller->gadget);
+	udc->gadget.dev.driver = NULL;
+	udc->driver = NULL;
 
-	/* unbind gadget and unhook driver. */
-	driver->unbind(&udc_controller->gadget);
-	udc_controller->gadget.dev.driver = NULL;
-	udc_controller->driver = NULL;
-
-	dev_info(udc_controller->dev, "unregistered gadget driver '%s'\r\n",
+	dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
 			driver->driver.name);
 	return 0;
 }
@@ -2502,7 +2431,7 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
 	ep->ep.ops = &qe_ep_ops;
 	ep->stopped = 1;
 	ep->ep.maxpacket = (unsigned short) ~0;
-	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->dir = 0xff;
 	ep->epnum = (u8)pipe_num;
 	ep->sent = 0;
@@ -2531,21 +2460,22 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
  *----------------------------------------------------------------------*/
 static void qe_udc_release(struct device *dev)
 {
-	int i = 0;
+	struct qe_udc *udc = container_of(dev, struct qe_udc, gadget.dev);
+	int i;
 
-	complete(udc_controller->done);
-	cpm_muram_free(cpm_muram_offset(udc_controller->ep_param[0]));
+	complete(udc->done);
+	cpm_muram_free(cpm_muram_offset(udc->ep_param[0]));
 	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
-		udc_controller->ep_param[i] = NULL;
+		udc->ep_param[i] = NULL;
 
-	kfree(udc_controller);
-	udc_controller = NULL;
+	kfree(udc);
 }
 
 /* Driver probe functions */
 static const struct of_device_id qe_udc_match[];
 static int __devinit qe_udc_probe(struct platform_device *ofdev)
 {
+	struct qe_udc *udc;
 	const struct of_device_id *match;
 	struct device_node *np = ofdev->dev.of_node;
 	struct qe_ep *ep;
@@ -2562,44 +2492,44 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev)
 		return -ENODEV;
 
 	/* Initialize the udc structure including QH member and other member */
-	udc_controller = qe_udc_config(ofdev);
-	if (!udc_controller) {
+	udc = qe_udc_config(ofdev);
+	if (!udc) {
 		dev_err(&ofdev->dev, "failed to initialize\n");
 		return -ENOMEM;
 	}
 
-	udc_controller->soc_type = (unsigned long)match->data;
-	udc_controller->usb_regs = of_iomap(np, 0);
-	if (!udc_controller->usb_regs) {
+	udc->soc_type = (unsigned long)match->data;
+	udc->usb_regs = of_iomap(np, 0);
+	if (!udc->usb_regs) {
 		ret = -ENOMEM;
 		goto err1;
 	}
 
 	/* initialize usb hw reg except for regs for EP,
 	 * leave usbintr reg untouched*/
-	qe_udc_reg_init(udc_controller);
+	qe_udc_reg_init(udc);
 
 	/* here comes the stand operations for probe
 	 * set the qe_udc->gadget.xxx */
-	udc_controller->gadget.ops = &qe_gadget_ops;
+	udc->gadget.ops = &qe_gadget_ops;
 
 	/* gadget.ep0 is a pointer */
-	udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
+	udc->gadget.ep0 = &udc->eps[0].ep;
 
-	INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
+	INIT_LIST_HEAD(&udc->gadget.ep_list);
 
 	/* modify in register gadget process */
-	udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
 
 	/* name: Identifies the controller hardware type. */
-	udc_controller->gadget.name = driver_name;
+	udc->gadget.name = driver_name;
 
-	device_initialize(&udc_controller->gadget.dev);
+	device_initialize(&udc->gadget.dev);
 
-	dev_set_name(&udc_controller->gadget.dev, "gadget");
+	dev_set_name(&udc->gadget.dev, "gadget");
 
-	udc_controller->gadget.dev.release = qe_udc_release;
-	udc_controller->gadget.dev.parent = &ofdev->dev;
+	udc->gadget.dev.release = qe_udc_release;
+	udc->gadget.dev.parent = &ofdev->dev;
 
 	/* initialize qe_ep struct */
 	for (i = 0; i < USB_MAX_ENDPOINTS ; i++) {
@@ -2608,104 +2538,104 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev)
 
 		/* setup the qe_ep struct and link ep.ep.list
 		 * into gadget.ep_list */
-		qe_ep_config(udc_controller, (unsigned char)i);
+		qe_ep_config(udc, (unsigned char)i);
 	}
 
 	/* ep0 initialization in here */
-	ret = qe_ep_init(udc_controller, 0, &qe_ep0_desc);
+	ret = qe_ep_init(udc, 0, &qe_ep0_desc);
 	if (ret)
 		goto err2;
 
 	/* create a buf for ZLP send, need to remain zeroed */
-	udc_controller->nullbuf = kzalloc(256, GFP_KERNEL);
-	if (udc_controller->nullbuf == NULL) {
-		dev_err(udc_controller->dev, "cannot alloc nullbuf\n");
+	udc->nullbuf = kzalloc(256, GFP_KERNEL);
+	if (udc->nullbuf == NULL) {
+		dev_err(udc->dev, "cannot alloc nullbuf\n");
 		ret = -ENOMEM;
 		goto err3;
 	}
 
 	/* buffer for data of get_status request */
-	udc_controller->statusbuf = kzalloc(2, GFP_KERNEL);
-	if (udc_controller->statusbuf == NULL) {
+	udc->statusbuf = kzalloc(2, GFP_KERNEL);
+	if (udc->statusbuf == NULL) {
 		ret = -ENOMEM;
 		goto err4;
 	}
 
-	udc_controller->nullp = virt_to_phys((void *)udc_controller->nullbuf);
-	if (udc_controller->nullp == DMA_ADDR_INVALID) {
-		udc_controller->nullp = dma_map_single(
-					udc_controller->gadget.dev.parent,
-					udc_controller->nullbuf,
+	udc->nullp = virt_to_phys((void *)udc->nullbuf);
+	if (udc->nullp == DMA_ADDR_INVALID) {
+		udc->nullp = dma_map_single(
+					udc->gadget.dev.parent,
+					udc->nullbuf,
 					256,
 					DMA_TO_DEVICE);
-		udc_controller->nullmap = 1;
+		udc->nullmap = 1;
 	} else {
-		dma_sync_single_for_device(udc_controller->gadget.dev.parent,
-					udc_controller->nullp, 256,
+		dma_sync_single_for_device(udc->gadget.dev.parent,
+					udc->nullp, 256,
 					DMA_TO_DEVICE);
 	}
 
-	tasklet_init(&udc_controller->rx_tasklet, ep_rx_tasklet,
-			(unsigned long)udc_controller);
+	tasklet_init(&udc->rx_tasklet, ep_rx_tasklet,
+			(unsigned long)udc);
 	/* request irq and disable DR  */
-	udc_controller->usb_irq = irq_of_parse_and_map(np, 0);
-	if (!udc_controller->usb_irq) {
+	udc->usb_irq = irq_of_parse_and_map(np, 0);
+	if (!udc->usb_irq) {
 		ret = -EINVAL;
 		goto err_noirq;
 	}
 
-	ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0,
-				driver_name, udc_controller);
+	ret = request_irq(udc->usb_irq, qe_udc_irq, 0,
+				driver_name, udc);
 	if (ret) {
-		dev_err(udc_controller->dev, "cannot request irq %d err %d \n",
-			udc_controller->usb_irq, ret);
+		dev_err(udc->dev, "cannot request irq %d err %d\n",
+				udc->usb_irq, ret);
 		goto err5;
 	}
 
-	ret = device_add(&udc_controller->gadget.dev);
+	ret = device_add(&udc->gadget.dev);
 	if (ret)
 		goto err6;
 
-	ret = usb_add_gadget_udc(&ofdev->dev, &udc_controller->gadget);
+	ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
 	if (ret)
 		goto err7;
 
-	dev_info(udc_controller->dev,
+	dev_set_drvdata(&ofdev->dev, udc);
+	dev_info(udc->dev,
 			"%s USB controller initialized as device\n",
-			(udc_controller->soc_type == PORT_QE) ? "QE" : "CPM");
+			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 	return 0;
 
 err7:
-	device_unregister(&udc_controller->gadget.dev);
+	device_unregister(&udc->gadget.dev);
 err6:
-	free_irq(udc_controller->usb_irq, udc_controller);
+	free_irq(udc->usb_irq, udc);
 err5:
-	irq_dispose_mapping(udc_controller->usb_irq);
+	irq_dispose_mapping(udc->usb_irq);
 err_noirq:
-	if (udc_controller->nullmap) {
-		dma_unmap_single(udc_controller->gadget.dev.parent,
-			udc_controller->nullp, 256,
+	if (udc->nullmap) {
+		dma_unmap_single(udc->gadget.dev.parent,
+			udc->nullp, 256,
 				DMA_TO_DEVICE);
-			udc_controller->nullp = DMA_ADDR_INVALID;
+			udc->nullp = DMA_ADDR_INVALID;
 	} else {
-		dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
-			udc_controller->nullp, 256,
+		dma_sync_single_for_cpu(udc->gadget.dev.parent,
+			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc_controller->statusbuf);
+	kfree(udc->statusbuf);
 err4:
-	kfree(udc_controller->nullbuf);
+	kfree(udc->nullbuf);
 err3:
-	ep = &udc_controller->eps[0];
+	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));
 	kfree(ep->rxframe);
 	kfree(ep->rxbuffer);
 	kfree(ep->txframe);
 err2:
-	iounmap(udc_controller->usb_regs);
+	iounmap(udc->usb_regs);
 err1:
-	kfree(udc_controller);
-	udc_controller = NULL;
+	kfree(udc);
 	return ret;
 }
 
@@ -2723,44 +2653,41 @@ static int qe_udc_resume(struct platform_device *dev)
 
 static int __devexit qe_udc_remove(struct platform_device *ofdev)
 {
+	struct qe_udc *udc = dev_get_drvdata(&ofdev->dev);
 	struct qe_ep *ep;
 	unsigned int size;
-
 	DECLARE_COMPLETION(done);
 
-	if (!udc_controller)
-		return -ENODEV;
+	usb_del_gadget_udc(&udc->gadget);
 
-	usb_del_gadget_udc(&udc_controller->gadget);
+	udc->done = &done;
+	tasklet_disable(&udc->rx_tasklet);
 
-	udc_controller->done = &done;
-	tasklet_disable(&udc_controller->rx_tasklet);
-
-	if (udc_controller->nullmap) {
-		dma_unmap_single(udc_controller->gadget.dev.parent,
-			udc_controller->nullp, 256,
+	if (udc->nullmap) {
+		dma_unmap_single(udc->gadget.dev.parent,
+			udc->nullp, 256,
 				DMA_TO_DEVICE);
-			udc_controller->nullp = DMA_ADDR_INVALID;
+			udc->nullp = DMA_ADDR_INVALID;
 	} else {
-		dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
-			udc_controller->nullp, 256,
+		dma_sync_single_for_cpu(udc->gadget.dev.parent,
+			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc_controller->statusbuf);
-	kfree(udc_controller->nullbuf);
+	kfree(udc->statusbuf);
+	kfree(udc->nullbuf);
 
-	ep = &udc_controller->eps[0];
+	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));
 	size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1);
 
 	kfree(ep->rxframe);
 	if (ep->rxbufmap) {
-		dma_unmap_single(udc_controller->gadget.dev.parent,
+		dma_unmap_single(udc->gadget.dev.parent,
 				ep->rxbuf_d, size,
 				DMA_FROM_DEVICE);
 		ep->rxbuf_d = DMA_ADDR_INVALID;
 	} else {
-		dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
+		dma_sync_single_for_cpu(udc->gadget.dev.parent,
 				ep->rxbuf_d, size,
 				DMA_FROM_DEVICE);
 	}
@@ -2768,14 +2695,14 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)
 	kfree(ep->rxbuffer);
 	kfree(ep->txframe);
 
-	free_irq(udc_controller->usb_irq, udc_controller);
-	irq_dispose_mapping(udc_controller->usb_irq);
+	free_irq(udc->usb_irq, udc);
+	irq_dispose_mapping(udc->usb_irq);
 
-	tasklet_kill(&udc_controller->rx_tasklet);
+	tasklet_kill(&udc->rx_tasklet);
 
-	iounmap(udc_controller->usb_regs);
+	iounmap(udc->usb_regs);
 
-	device_unregister(&udc_controller->gadget.dev);
+	device_unregister(&udc->gadget.dev);
 	/* wait for release() of gadget.dev to free udc */
 	wait_for_completion(&done);
 
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h
index 1da5fb03d218..4c07ca9cebf3 100644
--- a/drivers/usb/gadget/fsl_qe_udc.h
+++ b/drivers/usb/gadget/fsl_qe_udc.h
@@ -266,7 +266,6 @@ struct qe_ep {
 	struct usb_ep ep;
 	struct list_head queue;
 	struct qe_udc *udc;
-	const struct usb_endpoint_descriptor *desc;
 	struct usb_gadget *gadget;
 
 	u8 state;
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 0d9b2fa45af3..28316858208b 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -567,7 +567,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
 	ep = container_of(_ep, struct fsl_ep, ep);
 
 	/* catch various bogus parameters */
-	if (!_ep || !desc || ep->desc
+	if (!_ep || !desc || ep->ep.desc
 			|| (desc->bDescriptorType != USB_DT_ENDPOINT))
 		return -EINVAL;
 
@@ -608,7 +608,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
 
 	spin_lock_irqsave(&udc->lock, flags);
 	ep->ep.maxpacket = max;
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->stopped = 0;
 
 	/* Controller related setup */
@@ -632,7 +632,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
 	retval = 0;
 
 	VDBG("enabled %s (ep%d%s) maxpacket %d",ep->ep.name,
-			ep->desc->bEndpointAddress & 0x0f,
+			ep->ep.desc->bEndpointAddress & 0x0f,
 			(desc->bEndpointAddress & USB_DIR_IN)
 				? "in" : "out", max);
 en_done:
@@ -652,7 +652,7 @@ static int fsl_ep_disable(struct usb_ep *_ep)
 	int ep_num;
 
 	ep = container_of(_ep, struct fsl_ep, ep);
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		VDBG("%s not enabled", _ep ? ep->ep.name : NULL);
 		return -EINVAL;
 	}
@@ -675,7 +675,6 @@ static int fsl_ep_disable(struct usb_ep *_ep)
 	/* nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
 
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	spin_unlock_irqrestore(&udc->lock, flags);
@@ -754,6 +753,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
 		lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
 		lastreq->tail->next_td_ptr =
 			cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
+		/* Ensure dTD's next dtd pointer to be updated */
+		wmb();
 		/* Read prime bit, if 1 goto done */
 		if (fsl_readl(&dr_regs->endpointprime) & bitmask)
 			return;
@@ -892,11 +893,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		VDBG("%s, bad params", __func__);
 		return -EINVAL;
 	}
-	if (unlikely(!_ep || !ep->desc)) {
+	if (unlikely(!_ep || !ep->ep.desc)) {
 		VDBG("%s, bad ep", __func__);
 		return -EINVAL;
 	}
-	if (usb_endpoint_xfer_isoc(ep->desc)) {
+	if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
 		if (req->req.length > ep->ep.maxpacket)
 			return -EMSGSIZE;
 	}
@@ -1035,12 +1036,12 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
 
 	ep = container_of(_ep, struct fsl_ep, ep);
 	udc = ep->udc;
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		status = -EINVAL;
 		goto out;
 	}
 
-	if (usb_endpoint_xfer_isoc(ep->desc)) {
+	if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
 		status = -EOPNOTSUPP;
 		goto out;
 	}
@@ -1079,7 +1080,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)
 	struct ep_queue_head *qh;
 
 	ep = container_of(_ep, struct fsl_ep, ep);
-	if (!_ep || (!ep->desc && ep_index(ep) != 0))
+	if (!_ep || (!ep->ep.desc && ep_index(ep) != 0))
 		return -ENODEV;
 
 	udc = (struct fsl_udc *)ep->udc;
@@ -1112,7 +1113,7 @@ static void fsl_ep_fifo_flush(struct usb_ep *_ep)
 		return;
 	} else {
 		ep = container_of(_ep, struct fsl_ep, ep);
-		if (!ep->desc)
+		if (!ep->ep.desc)
 			return;
 	}
 	ep_num = ep_index(ep);
@@ -1367,7 +1368,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 		target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index));
 
 		/* stall if endpoint doesn't exist */
-		if (!target_ep->desc)
+		if (!target_ep->ep.desc)
 			goto stall;
 		tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep))
 				<< USB_ENDPOINT_HALT;
@@ -2277,7 +2278,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
 	}
 	/* other gadget->eplist ep */
 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
-		if (ep->desc) {
+		if (ep->ep.desc) {
 			t = scnprintf(next, size,
 					"\nFor %s Maxpkt is 0x%x "
 					"index is 0x%x\n",
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 1212646841a3..5cd7b7e7ddb4 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -461,7 +461,6 @@ struct fsl_ep {
 	struct list_head queue;
 	struct fsl_udc *udc;
 	struct ep_queue_head *qh;
-	const struct usb_endpoint_descriptor *desc;
 	struct usb_gadget *gadget;
 
 	char name[14];
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
index 5831cb4a0b35..cdd94540e1cd 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -203,7 +203,7 @@ static int config_ep(struct fusb300_ep *ep,
 	struct fusb300 *fusb300 = ep->fusb300;
 	struct fusb300_ep_info info;
 
-	ep->desc = desc;
+	ep->ep.desc = desc;
 
 	info.interval = 0;
 	info.addrofs = 0;
@@ -443,7 +443,7 @@ static int fusb300_queue(struct usb_ep *_ep, struct usb_request *_req,
 	req->req.actual = 0;
 	req->req.status = -EINPROGRESS;
 
-	if (ep->desc == NULL) /* ep0 */
+	if (ep->ep.desc == NULL) /* ep0 */
 		ep0_queue(ep, req);
 	else if (request && !ep->stall)
 		enable_fifo_int(ep);
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h
index 92745bd03064..542cd83cc806 100644
--- a/drivers/usb/gadget/fusb300_udc.h
+++ b/drivers/usb/gadget/fusb300_udc.h
@@ -650,7 +650,6 @@ struct fusb300_ep {
 
 	unsigned char		epnum;
 	unsigned char		type;
-	const struct usb_endpoint_descriptor	*desc;
 };
 
 struct fusb300 {
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h
index e84b3c47ed3c..71ca193358b8 100644
--- a/drivers/usb/gadget/g_zero.h
+++ b/drivers/usb/gadget/g_zero.h
@@ -13,10 +13,11 @@ extern unsigned buflen;
 extern const struct usb_descriptor_header *otg_desc[];
 
 /* common utilities */
-struct usb_request *alloc_ep_req(struct usb_ep *ep);
+struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
 void free_ep_req(struct usb_ep *ep, struct usb_request *req);
 void disable_endpoints(struct usb_composite_dev *cdev,
-		struct usb_ep *in, struct usb_ep *out);
+		struct usb_ep *in, struct usb_ep *out,
+		struct usb_ep *iso_in, struct usb_ep *iso_out);
 
 /* configuration-specific linkup */
 int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume);
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index e151d6b87dee..b241e6c6a7f2 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -102,7 +102,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	unsigned long	flags;
 
 	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep || !desc || ep->desc
+	if (!_ep || !desc || ep->ep.desc
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
 	dev = ep->dev;
@@ -176,7 +176,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	command(ep->dev->regs, COMMAND_RESET, ep->num);
 	ep->ep.maxpacket = max;
 	ep->stopped = 0;
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	spin_unlock_irqrestore(&ep->dev->lock, flags);
 
 	DBG(dev, "enable %s %s %s maxpacket %u\n", ep->ep.name,
@@ -233,7 +233,6 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
 	}
 
 	ep->ep.maxpacket = MAX_FIFO_SIZE;
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->irqs = 0;
@@ -247,7 +246,7 @@ static int goku_ep_disable(struct usb_ep *_ep)
 	unsigned long	flags;
 
 	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep || !ep->desc)
+	if (!_ep || !ep->ep.desc)
 		return -ENODEV;
 	dev = ep->dev;
 	if (dev->ep0state == EP0_SUSPEND)
@@ -722,7 +721,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 			|| !_req->buf || !list_empty(&req->queue)))
 		return -EINVAL;
 	ep = container_of(_ep, struct goku_ep, ep);
-	if (unlikely(!_ep || (!ep->desc && ep->num != 0)))
+	if (unlikely(!_ep || (!ep->ep.desc && ep->num != 0)))
 		return -EINVAL;
 	dev = ep->dev;
 	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))
@@ -815,7 +814,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 	unsigned long		flags;
 
 	ep = container_of(_ep, struct goku_ep, ep);
-	if (!_ep || !_req || (!ep->desc && ep->num != 0))
+	if (!_ep || !_req || (!ep->ep.desc && ep->num != 0))
 		return -EINVAL;
 	dev = ep->dev;
 	if (!dev->driver)
@@ -896,7 +895,7 @@ static int goku_set_halt(struct usb_ep *_ep, int value)
 			return -EINVAL;
 
 	/* don't change EPxSTATUS_EP_INVALID to READY */
-	} else if (!ep->desc) {
+	} else if (!ep->ep.desc) {
 		DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
 		return -EINVAL;
 	}
@@ -955,7 +954,7 @@ static void goku_fifo_flush(struct usb_ep *_ep)
 	VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name);
 
 	/* don't change EPxSTATUS_EP_INVALID to READY */
-	if (!ep->desc && ep->num != 0) {
+	if (!ep->ep.desc && ep->num != 0) {
 		DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
 		return;
 	}
@@ -1152,7 +1151,7 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
 		struct goku_ep		*ep = &dev->ep [i];
 		struct goku_request	*req;
 
-		if (i && !ep->desc)
+		if (i && !ep->ep.desc)
 			continue;
 
 		tmp = readl(ep->reg_status);
@@ -1473,7 +1472,8 @@ static void ep0_setup(struct goku_udc *dev)
 			case USB_RECIP_ENDPOINT:
 				tmp = le16_to_cpu(ctrl.wIndex) & 0x0f;
 				/* active endpoint */
-				if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0))
+				if (tmp > 3 ||
+				    (!dev->ep[tmp].ep.desc && tmp != 0))
 					goto stall;
 				if (ctrl.wIndex & cpu_to_le16(
 						USB_DIR_IN)) {
@@ -1895,14 +1895,4 @@ static struct pci_driver goku_pci_driver = {
 	/* FIXME add power management support */
 };
 
-static int __init init (void)
-{
-	return pci_register_driver (&goku_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	pci_unregister_driver (&goku_pci_driver);
-}
-module_exit (cleanup);
+module_pci_driver(goku_pci_driver);
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index e7e0c69d3b1f..85cdce0d1901 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -216,7 +216,6 @@ struct goku_ep {
 
 	/* analogous to a host-side qh */
 	struct list_head			queue;
-	const struct usb_endpoint_descriptor	*desc;
 
 	u32 __iomem				*reg_fifo;
 	u32 __iomem				*reg_mode;
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index 8d1c75abd73d..54034f84f992 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1237,14 +1237,15 @@ irq_handler_t intr_handler(int i)
  *******************************************************************************
  */
 
-static int imx_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *));
-static int imx_udc_stop(struct usb_gadget_driver *driver);
+static int imx_udc_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
+static int imx_udc_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver);
 static const struct usb_gadget_ops imx_udc_ops = {
-	.get_frame	 = imx_udc_get_frame,
-	.wakeup		 = imx_udc_wakeup,
-	.start		= imx_udc_start,
-	.stop		= imx_udc_stop,
+	.get_frame	= imx_udc_get_frame,
+	.wakeup		= imx_udc_wakeup,
+	.udc_start	= imx_udc_start,
+	.udc_stop	= imx_udc_stop,
 };
 
 static struct imx_udc_struct controller = {
@@ -1329,23 +1330,13 @@ static struct imx_udc_struct controller = {
  * USB gadget driver functions
  *******************************************************************************
  */
-static int imx_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
+static int imx_udc_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct imx_udc_struct *imx_usb = &controller;
+	struct imx_udc_struct *imx_usb;
 	int retval;
 
-	if (!driver
-		|| driver->max_speed < USB_SPEED_FULL
-		|| !bind
-		|| !driver->disconnect
-		|| !driver->setup)
-			return -EINVAL;
-	if (!imx_usb)
-		return -ENODEV;
-	if (imx_usb->driver)
-		return -EBUSY;
-
+	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
 	/* first hook up the driver ... */
 	imx_usb->driver = driver;
 	imx_usb->gadget.dev.driver = &driver->driver;
@@ -1353,14 +1344,6 @@ static int imx_udc_start(struct usb_gadget_driver *driver,
 	retval = device_add(&imx_usb->gadget.dev);
 	if (retval)
 		goto fail;
-	retval = bind(&imx_usb->gadget);
-	if (retval) {
-		D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n",
-			__func__, driver->driver.name, retval);
-		device_del(&imx_usb->gadget.dev);
-
-		goto fail;
-	}
 
 	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
 		__func__, driver->driver.name);
@@ -1374,20 +1357,16 @@ fail:
 	return retval;
 }
 
-static int imx_udc_stop(struct usb_gadget_driver *driver)
+static int imx_udc_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct imx_udc_struct *imx_usb = &controller;
-
-	if (!imx_usb)
-		return -ENODEV;
-	if (!driver || driver != imx_usb->driver || !driver->unbind)
-		return -EINVAL;
+	struct imx_udc_struct *imx_usb = container_of(gadget,
+			struct imx_udc_struct, gadget);
 
 	udc_stop_activity(imx_usb, driver);
 	imx_udc_disable(imx_usb);
 	del_timer(&imx_usb->timer);
 
-	driver->unbind(&imx_usb->gadget);
 	imx_usb->gadget.dev.driver = NULL;
 	imx_usb->driver = NULL;
 
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index f9cedd52cf20..e119519cdaf4 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -154,7 +154,7 @@ static inline void print_all_registers(struct langwell_udc *dev)
 /*-------------------------------------------------------------------------*/
 
 #define	is_in(ep)	(((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir ==	\
-			USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc)))
+			USB_DIR_IN) : (usb_endpoint_dir_in((ep)->ep.desc)))
 
 #define	DIR_STRING(ep)	(is_in(ep) ? "in" : "out")
 
@@ -257,7 +257,7 @@ static int langwell_ep_enable(struct usb_ep *_ep,
 	dev = ep->dev;
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (!_ep || !desc || ep->desc
+	if (!_ep || !desc || ep->ep.desc
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
 
@@ -337,7 +337,7 @@ static int langwell_ep_enable(struct usb_ep *_ep,
 	spin_lock_irqsave(&dev->lock, flags);
 
 	ep->ep.maxpacket = max;
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->stopped = 0;
 	ep->ep_num = usb_endpoint_num(desc);
 
@@ -432,7 +432,7 @@ static void nuke(struct langwell_ep *ep, int status)
 	ep->stopped = 1;
 
 	/* endpoint fifo flush */
-	if (&ep->ep && ep->desc)
+	if (&ep->ep && ep->ep.desc)
 		langwell_ep_fifo_flush(&ep->ep);
 
 	while (!list_empty(&ep->queue)) {
@@ -459,7 +459,7 @@ static int langwell_ep_disable(struct usb_ep *_ep)
 	dev = ep->dev;
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (!_ep || !ep->desc)
+	if (!_ep || !ep->ep.desc)
 		return -EINVAL;
 
 	spin_lock_irqsave(&dev->lock, flags);
@@ -476,7 +476,6 @@ static int langwell_ep_disable(struct usb_ep *_ep)
 	/* nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
 
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
@@ -752,14 +751,14 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
 		return -EINVAL;
 	}
 
-	if (unlikely(!_ep || !ep->desc))
+	if (unlikely(!_ep || !ep->ep.desc))
 		return -EINVAL;
 
 	dev = ep->dev;
 	req->ep = ep;
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (usb_endpoint_xfer_isoc(ep->desc)) {
+	if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
 		if (req->req.length > ep->ep.maxpacket)
 			return -EMSGSIZE;
 		is_iso = 1;
@@ -822,7 +821,7 @@ static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 	dev = ep->dev;
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (!_ep || !ep->desc || !_req)
+	if (!_ep || !ep->ep.desc || !_req)
 		return -EINVAL;
 
 	if (!dev->driver)
@@ -950,13 +949,13 @@ static int langwell_ep_set_halt(struct usb_ep *_ep, int value)
 
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (!_ep || !ep->desc)
+	if (!_ep || !ep->ep.desc)
 		return -EINVAL;
 
 	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 
-	if (usb_endpoint_xfer_isoc(ep->desc))
+	if (usb_endpoint_xfer_isoc(ep->ep.desc))
 		return  -EOPNOTSUPP;
 
 	spin_lock_irqsave(&dev->lock, flags);
@@ -999,7 +998,7 @@ static int langwell_ep_set_wedge(struct usb_ep *_ep)
 
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (!_ep || !ep->desc)
+	if (!_ep || !ep->ep.desc)
 		return -EINVAL;
 
 	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
@@ -1020,8 +1019,8 @@ static void langwell_ep_fifo_flush(struct usb_ep *_ep)
 
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (!_ep || !ep->desc) {
-		dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n");
+	if (!_ep || !ep->ep.desc) {
+		dev_vdbg(&dev->pdev->dev, "ep or ep->ep.desc is NULL\n");
 		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		return;
 	}
@@ -1402,7 +1401,7 @@ static int eps_reinit(struct langwell_udc *dev)
 	ep->stopped = 0;
 	ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
 	ep->ep_num = 0;
-	ep->desc = &langwell_ep0_desc;
+	ep->ep.desc = &langwell_ep0_desc;
 	INIT_LIST_HEAD(&ep->queue);
 
 	ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
@@ -1737,7 +1736,7 @@ static ssize_t show_langwell_udc(struct device *_dev,
 	}
 	/* other gadget->eplist ep */
 	list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
-		if (ep->desc) {
+		if (ep->ep.desc) {
 			t = scnprintf(next, size,
 					"\n%s MaxPacketSize: 0x%x, "
 					"ep_num: %d\n",
@@ -2046,10 +2045,10 @@ static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev,
 
 	list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
 		u8	bEndpointAddress;
-		if (!ep->desc)
+		if (!ep->ep.desc)
 			continue;
 
-		bEndpointAddress = ep->desc->bEndpointAddress;
+		bEndpointAddress = ep->ep.desc->bEndpointAddress;
 		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
 			continue;
 
@@ -3412,23 +3411,9 @@ static struct pci_driver langwell_pci_driver = {
 	.shutdown =	langwell_udc_shutdown,
 };
 
-
-static int __init init(void)
-{
-	return pci_register_driver(&langwell_pci_driver);
-}
-module_init(init);
-
-
-static void __exit cleanup(void)
-{
-	pci_unregister_driver(&langwell_pci_driver);
-}
-module_exit(cleanup);
-
+module_pci_driver(langwell_pci_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>");
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
index 8c8087abb481..38fa3c86d85c 100644
--- a/drivers/usb/gadget/langwell_udc.h
+++ b/drivers/usb/gadget/langwell_udc.h
@@ -116,7 +116,6 @@ struct langwell_ep {
 	unsigned long		irqs;
 	struct list_head	queue;
 	struct langwell_dqh	*dqh;
-	const struct usb_endpoint_descriptor	*desc;
 	char			name[14];
 	unsigned		stopped:1,
 				ep_type:2,
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 3608b3bd5732..8981fbb5748c 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -390,7 +390,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 	int *counter;
 	int ret;
 
-	ep->desc = desc;
+	ep->ep.desc = desc;
 
 	BUG_ON(ep->pipenum);
 
@@ -558,7 +558,7 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
 
 static void start_packet(struct m66592_ep *ep, struct m66592_request *req)
 {
-	if (ep->desc->bEndpointAddress & USB_DIR_IN)
+	if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
 		start_packet_write(ep, req);
 	else
 		start_packet_read(ep, req);
@@ -734,7 +734,7 @@ __acquires(m66592->lock)
 
 	if (restart) {
 		req = list_entry(ep->queue.next, struct m66592_request, queue);
-		if (ep->desc)
+		if (ep->ep.desc)
 			start_packet(ep, req);
 	}
 }
@@ -917,7 +917,7 @@ static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
 				ep = m66592->pipenum2ep[pipenum];
 				req = list_entry(ep->queue.next,
 						 struct m66592_request, queue);
-				if (ep->desc->bEndpointAddress & USB_DIR_IN)
+				if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
 					irq_packet_write(ep, req);
 				else
 					irq_packet_read(ep, req);
@@ -1377,7 +1377,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
 	req->req.actual = 0;
 	req->req.status = -EINPROGRESS;
 
-	if (ep->desc == NULL)	/* control */
+	if (ep->ep.desc == NULL)	/* control */
 		start_ep0(ep, req);
 	else {
 		if (request && !ep->busy)
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index 9d9f7e39f037..88c85b4116a2 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -456,7 +456,7 @@ struct m66592_ep {
 	unsigned		use_dma:1;
 	u16			pipenum;
 	u16			type;
-	const struct usb_endpoint_descriptor	*desc;
+
 	/* register address */
 	unsigned long		fifoaddr;
 	unsigned long		fifosel;
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
index e2be9519abbe..9073436d8b24 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/mv_udc.h
@@ -232,7 +232,6 @@ struct mv_ep {
 	struct mv_udc		*udc;
 	struct list_head	queue;
 	struct mv_dqh		*dqh;
-	const struct usb_endpoint_descriptor	*desc;
 	u32			direction;
 	char			name[14];
 	unsigned		stopped:1,
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index a73cf406e2a4..dbcd1329495e 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -464,7 +464,7 @@ static int mv_ep_enable(struct usb_ep *_ep,
 	ep = container_of(_ep, struct mv_ep, ep);
 	udc = ep->udc;
 
-	if (!_ep || !desc || ep->desc
+	if (!_ep || !desc || ep->ep.desc
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
 
@@ -528,7 +528,7 @@ static int mv_ep_enable(struct usb_ep *_ep,
 	dqh->size_ioc_int_sts = 0;
 
 	ep->ep.maxpacket = max;
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->stopped = 0;
 
 	/* Enable the endpoint for Rx or Tx and set the endpoint type */
@@ -580,7 +580,7 @@ static int  mv_ep_disable(struct usb_ep *_ep)
 	unsigned long flags;
 
 	ep = container_of(_ep, struct mv_ep, ep);
-	if ((_ep == NULL) || !ep->desc)
+	if ((_ep == NULL) || !ep->ep.desc)
 		return -EINVAL;
 
 	udc = ep->udc;
@@ -606,7 +606,6 @@ static int  mv_ep_disable(struct usb_ep *_ep)
 	/* nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
 
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
@@ -651,7 +650,7 @@ static void mv_ep_fifo_flush(struct usb_ep *_ep)
 		return;
 
 	ep = container_of(_ep, struct mv_ep, ep);
-	if (!ep->desc)
+	if (!ep->ep.desc)
 		return;
 
 	udc = ep->udc;
@@ -715,11 +714,11 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		dev_err(&udc->dev->dev, "%s, bad params", __func__);
 		return -EINVAL;
 	}
-	if (unlikely(!_ep || !ep->desc)) {
+	if (unlikely(!_ep || !ep->ep.desc)) {
 		dev_err(&udc->dev->dev, "%s, bad ep", __func__);
 		return -EINVAL;
 	}
-	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+	if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
 		if (req->req.length > ep->ep.maxpacket)
 			return -EMSGSIZE;
 	}
@@ -925,12 +924,12 @@ static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
 
 	ep = container_of(_ep, struct mv_ep, ep);
 	udc = ep->udc;
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		status = -EINVAL;
 		goto out;
 	}
 
-	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+	if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
 		status = -EOPNOTSUPP;
 		goto out;
 	}
@@ -1279,7 +1278,7 @@ static int eps_init(struct mv_udc *udc)
 	ep->stopped = 0;
 	ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
 	ep->ep_num = 0;
-	ep->desc = &mv_ep0_desc;
+	ep->ep.desc = &mv_ep0_desc;
 	INIT_LIST_HEAD(&ep->queue);
 
 	ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 3b4b6dd0f95a..7ba32469c5bd 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -153,7 +153,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
 	u16		maxp;
 
 	/* catch various bogus parameters */
-	if (!_ep || !desc || ep->desc
+	if (!_ep || !desc || ep->ep.desc
 			|| desc->bDescriptorType != USB_DT_ENDPOINT
 			|| ep->bEndpointAddress != desc->bEndpointAddress
 			|| ep->maxpacket < usb_endpoint_maxp(desc)) {
@@ -200,7 +200,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
 
 	spin_lock_irqsave(&udc->lock, flags);
 
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->irqs = 0;
 	ep->stopped = 0;
 	ep->ep.maxpacket = maxp;
@@ -242,14 +242,13 @@ static int omap_ep_disable(struct usb_ep *_ep)
 	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
 	unsigned long	flags;
 
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		DBG("%s, %s not enabled\n", __func__,
 			_ep ? ep->ep.name : NULL);
 		return -EINVAL;
 	}
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	nuke (ep, -ESHUTDOWN);
 	ep->ep.maxpacket = ep->maxpacket;
@@ -917,7 +916,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		DBG("%s, bad params\n", __func__);
 		return -EINVAL;
 	}
-	if (!_ep || (!ep->desc && ep->bEndpointAddress)) {
+	if (!_ep || (!ep->ep.desc && ep->bEndpointAddress)) {
 		DBG("%s, bad ep\n", __func__);
 		return -EINVAL;
 	}
@@ -1121,7 +1120,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
 			status = 0;
 
 	/* otherwise, all active non-ISO endpoints can halt */
-	} else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->desc) {
+	} else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->ep.desc) {
 
 		/* IN endpoints must already be idle */
 		if ((ep->bEndpointAddress & USB_DIR_IN)
@@ -1625,7 +1624,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 				if (w_index & USB_DIR_IN)
 					ep += 16;
 				if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-						|| !ep->desc)
+						|| !ep->ep.desc)
 					goto do_stall;
 				use_ep(ep, 0);
 				omap_writew(udc->clr_halt, UDC_CTRL);
@@ -1653,7 +1652,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
 			if (w_index & USB_DIR_IN)
 				ep += 16;
 			if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-					|| ep == ep0 || !ep->desc)
+					|| ep == ep0 || !ep->ep.desc)
 				goto do_stall;
 			if (use_dma && ep->has_dma) {
 				/* this has rude side-effects (aborts) and
@@ -1688,7 +1687,7 @@ ep0out_status_stage:
 			ep = &udc->ep[w_index & 0xf];
 			if (w_index & USB_DIR_IN)
 				ep += 16;
-			if (!ep->desc)
+			if (!ep->ep.desc)
 				goto do_stall;
 
 			/* iso never stalls */
@@ -2509,7 +2508,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
 		if (tmp & UDC_ADD) {
 			list_for_each_entry (ep, &udc->gadget.ep_list,
 					ep.ep_list) {
-				if (ep->desc)
+				if (ep->ep.desc)
 					proc_ep_show(s, ep);
 			}
 		}
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 59d3b2213cb1..cfadeb5fc5de 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -140,7 +140,6 @@ struct omap_ep {
 	struct list_head		queue;
 	unsigned long			irqs;
 	struct list_head		iso;
-	const struct usb_endpoint_descriptor	*desc;
 	char				name[14];
 	u16				maxpacket;
 	u8				bEndpointAddress;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 65307064a6fd..1cfcc9ecbfbc 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -295,7 +295,6 @@ struct pch_udc_ep {
 	struct pch_udc_data_dma_desc	*td_data;
 	struct pch_udc_dev		*dev;
 	unsigned long			offset_addr;
-	const struct usb_endpoint_descriptor	*desc;
 	struct list_head		queue;
 	unsigned			num:5,
 					in:1,
@@ -1705,7 +1704,7 @@ static int pch_udc_pcd_ep_enable(struct usb_ep *usbep,
 	if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
 		return -ESHUTDOWN;
 	spin_lock_irqsave(&dev->lock, iflags);
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->halted = 0;
 	pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc);
 	ep->ep.maxpacket = usb_endpoint_maxp(desc);
@@ -1734,7 +1733,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
 
 	ep = container_of(usbep, struct pch_udc_ep, ep);
 	dev = ep->dev;
-	if ((usbep->name == ep0_string) || !ep->desc)
+	if ((usbep->name == ep0_string) || !ep->ep.desc)
 		return -EINVAL;
 
 	spin_lock_irqsave(&ep->dev->lock, iflags);
@@ -1742,7 +1741,6 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
 	ep->halted = 1;
 	pch_udc_ep_disable(ep);
 	pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	INIT_LIST_HEAD(&ep->queue);
 	spin_unlock_irqrestore(&ep->dev->lock, iflags);
@@ -1849,7 +1847,7 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
 		return -EINVAL;
 	ep = container_of(usbep, struct pch_udc_ep, ep);
 	dev = ep->dev;
-	if (!ep->desc && ep->num)
+	if (!ep->ep.desc && ep->num)
 		return -EINVAL;
 	req = container_of(usbreq, struct pch_udc_request, req);
 	if (!list_empty(&req->queue))
@@ -1949,7 +1947,7 @@ static int pch_udc_pcd_dequeue(struct usb_ep *usbep,
 
 	ep = container_of(usbep, struct pch_udc_ep, ep);
 	dev = ep->dev;
-	if (!usbep || !usbreq || (!ep->desc && ep->num))
+	if (!usbep || !usbreq || (!ep->ep.desc && ep->num))
 		return ret;
 	req = container_of(usbreq, struct pch_udc_request, req);
 	spin_lock_irqsave(&ep->dev->lock, flags);
@@ -1988,7 +1986,7 @@ static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt)
 		return -EINVAL;
 	ep = container_of(usbep, struct pch_udc_ep, ep);
 	dev = ep->dev;
-	if (!ep->desc && !ep->num)
+	if (!ep->ep.desc && !ep->num)
 		return -EINVAL;
 	if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
 		return -ESHUTDOWN;
@@ -2033,7 +2031,7 @@ static int pch_udc_pcd_set_wedge(struct usb_ep *usbep)
 		return -EINVAL;
 	ep = container_of(usbep, struct pch_udc_ep, ep);
 	dev = ep->dev;
-	if (!ep->desc && !ep->num)
+	if (!ep->ep.desc && !ep->num)
 		return -EINVAL;
 	if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
 		return -ESHUTDOWN;
@@ -2065,7 +2063,7 @@ static void pch_udc_pcd_fifo_flush(struct usb_ep *usbep)
 		return;
 
 	ep = container_of(usbep, struct pch_udc_ep, ep);
-	if (ep->desc || !ep->num)
+	if (ep->ep.desc || !ep->num)
 		pch_udc_ep_fifo_flush(ep, ep->in);
 }
 
@@ -3282,7 +3280,6 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
 
 MODULE_DEVICE_TABLE(pci, pch_udc_pcidev_id);
 
-
 static struct pci_driver pch_udc_driver = {
 	.name =	KBUILD_MODNAME,
 	.id_table =	pch_udc_pcidev_id,
@@ -3293,17 +3290,7 @@ static struct pci_driver pch_udc_driver = {
 	.shutdown =	pch_udc_shutdown,
 };
 
-static int __init pch_udc_pci_init(void)
-{
-	return pci_register_driver(&pch_udc_driver);
-}
-module_init(pch_udc_pci_init);
-
-static void __exit pch_udc_pci_exit(void)
-{
-	pci_unregister_driver(&pch_udc_driver);
-}
-module_exit(pch_udc_pci_exit);
+module_pci_driver(pch_udc_driver);
 
 MODULE_DESCRIPTION("Intel EG20T USB Device Controller");
 MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>");
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 4e4dc1f5f388..f1f9290a2f47 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -51,6 +51,7 @@
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
+#include "composite.c"
 #include "usbstring.c"
 #include "config.c"
 #include "epautoconf.c"
@@ -75,8 +76,6 @@ struct printer_dev {
 	/* lock buffer lists during read/write calls */
 	struct mutex		lock_printer_io;
 	struct usb_gadget	*gadget;
-	struct usb_request	*req;		/* for control responses */
-	u8			config;
 	s8			interface;
 	struct usb_ep		*in_ep, *out_ep;
 
@@ -100,6 +99,7 @@ struct printer_dev {
 	struct device		*pdev;
 	u8			printer_cdev_open;
 	wait_queue_head_t	wait;
+	struct usb_function	function;
 };
 
 static struct printer_dev usb_printer_gadget;
@@ -120,26 +120,6 @@ static struct printer_dev usb_printer_gadget;
  * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
  */
 
-static ushort idVendor;
-module_param(idVendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(idVendor, "USB Vendor ID");
-
-static ushort idProduct;
-module_param(idProduct, ushort, S_IRUGO);
-MODULE_PARM_DESC(idProduct, "USB Product ID");
-
-static ushort bcdDevice;
-module_param(bcdDevice, ushort, S_IRUGO);
-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
-
-static char *iManufacturer;
-module_param(iManufacturer, charp, S_IRUGO);
-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
-
-static char *iProduct;
-module_param(iProduct, charp, S_IRUGO);
-MODULE_PARM_DESC(iProduct, "USB Product string");
-
 static char *iSerialNum;
 module_param(iSerialNum, charp, S_IRUGO);
 MODULE_PARM_DESC(iSerialNum, "1");
@@ -154,47 +134,8 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
 
 #define QLEN	qlen
 
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-#define DEVSPEED	USB_SPEED_HIGH
-#else   /* full speed (low speed doesn't do bulk) */
-#define DEVSPEED        USB_SPEED_FULL
-#endif
-
 /*-------------------------------------------------------------------------*/
 
-#define xprintk(d, level, fmt, args...) \
-	printk(level "%s: " fmt, DRIVER_DESC, ## args)
-
-#ifdef DEBUG
-#define DBG(dev, fmt, args...) \
-	xprintk(dev, KERN_DEBUG, fmt, ## args)
-#else
-#define DBG(dev, fmt, args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDBG(dev, fmt, args...) \
-	xprintk(dev, KERN_DEBUG, fmt, ## args)
-#else
-#define VDBG(dev, fmt, args...) \
-	do { } while (0)
-#endif /* VERBOSE */
-
-#define ERROR(dev, fmt, args...) \
-	xprintk(dev, KERN_ERR, fmt, ## args)
-#define WARNING(dev, fmt, args...) \
-	xprintk(dev, KERN_WARNING, fmt, ## args)
-#define INFO(dev, fmt, args...) \
-	xprintk(dev, KERN_INFO, fmt, ## args)
-
-/*-------------------------------------------------------------------------*/
-
-/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
- * ep0 implementation:  descriptors, config management, setup().
- * also optional class-specific notification interrupt transfer.
- */
-
 /*
  * DESCRIPTORS ... most are static, but strings and (full) configuration
  * descriptors are built on demand.
@@ -227,24 +168,6 @@ static struct usb_device_descriptor device_desc = {
 	.bNumConfigurations =	1
 };
 
-static struct usb_otg_descriptor otg_desc = {
-	.bLength =		sizeof otg_desc,
-	.bDescriptorType =	USB_DT_OTG,
-	.bmAttributes =		USB_OTG_SRP
-};
-
-static struct usb_config_descriptor config_desc = {
-	.bLength =		sizeof config_desc,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	DEV_CONFIG_VALUE,
-	.iConfiguration =	0,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		CONFIG_USB_GADGET_VBUS_DRAW / 2,
-};
-
 static struct usb_interface_descriptor intf_desc = {
 	.bLength =		sizeof intf_desc,
 	.bDescriptorType =	USB_DT_INTERFACE,
@@ -270,16 +193,13 @@ static struct usb_endpoint_descriptor fs_ep_out_desc = {
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK
 };
 
-static const struct usb_descriptor_header *fs_printer_function [11] = {
-	(struct usb_descriptor_header *) &otg_desc,
+static struct usb_descriptor_header *fs_printer_function[] = {
 	(struct usb_descriptor_header *) &intf_desc,
 	(struct usb_descriptor_header *) &fs_ep_in_desc,
 	(struct usb_descriptor_header *) &fs_ep_out_desc,
 	NULL
 };
 
-#ifdef	CONFIG_USB_GADGET_DUALSPEED
-
 /*
  * usb 2.0 devices need to expose both high speed and full speed
  * descriptors, unless they only run at full speed.
@@ -307,24 +227,27 @@ static struct usb_qualifier_descriptor dev_qualifier = {
 	.bNumConfigurations =	1
 };
 
-static const struct usb_descriptor_header *hs_printer_function [11] = {
-	(struct usb_descriptor_header *) &otg_desc,
+static struct usb_descriptor_header *hs_printer_function[] = {
 	(struct usb_descriptor_header *) &intf_desc,
 	(struct usb_descriptor_header *) &hs_ep_in_desc,
 	(struct usb_descriptor_header *) &hs_ep_out_desc,
 	NULL
 };
 
+static struct usb_otg_descriptor otg_descriptor = {
+	.bLength =              sizeof otg_descriptor,
+	.bDescriptorType =      USB_DT_OTG,
+	.bmAttributes =         USB_OTG_SRP,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &otg_descriptor,
+	NULL,
+};
+
 /* maxpacket and other transfer characteristics vary by speed. */
 #define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs))
 
-#else
-
-/* if there's no high speed support, maxpacket doesn't change. */
-#define ep_desc(g, hs, fs) (((void)(g)), (fs))
-
-#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
-
 /*-------------------------------------------------------------------------*/
 
 /* descriptors that are built on-demand */
@@ -343,11 +266,16 @@ static struct usb_string		strings [] = {
 	{  }		/* end of list */
 };
 
-static struct usb_gadget_strings	stringtab = {
+static struct usb_gadget_strings	stringtab_dev = {
 	.language	= 0x0409,	/* en-us */
 	.strings	= strings,
 };
 
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
@@ -937,82 +865,8 @@ static void printer_reset_interface(struct printer_dev *dev)
 	dev->interface = -1;
 }
 
-/* change our operational config.  must agree with the code
- * that returns config descriptors, and altsetting code.
- */
-static int
-printer_set_config(struct printer_dev *dev, unsigned number)
-{
-	int			result = 0;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	switch (number) {
-	case DEV_CONFIG_VALUE:
-		result = 0;
-		break;
-	default:
-		result = -EINVAL;
-		/* FALL THROUGH */
-	case 0:
-		break;
-	}
-
-	if (result) {
-		usb_gadget_vbus_draw(dev->gadget,
-				dev->gadget->is_otg ? 8 : 100);
-	} else {
-		unsigned power;
-
-		power = 2 * config_desc.bMaxPower;
-		usb_gadget_vbus_draw(dev->gadget, power);
-
-		dev->config = number;
-		INFO(dev, "%s config #%d: %d mA, %s\n",
-		     usb_speed_string(gadget->speed),
-		     number, power, driver_desc);
-	}
-	return result;
-}
-
-static int
-config_buf(enum usb_device_speed speed, u8 *buf, u8 type, unsigned index,
-		int is_otg)
-{
-	int					len;
-	const struct usb_descriptor_header	**function;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-	int					hs = (speed == USB_SPEED_HIGH);
-
-	if (type == USB_DT_OTHER_SPEED_CONFIG)
-		hs = !hs;
-
-	if (hs) {
-		function = hs_printer_function;
-	} else {
-		function = fs_printer_function;
-	}
-#else
-	function = fs_printer_function;
-#endif
-
-	if (index >= device_desc.bNumConfigurations)
-		return -EINVAL;
-
-	/* for now, don't advertise srp-only devices */
-	if (!is_otg)
-		function++;
-
-	len = usb_gadget_config_buf(&config_desc, buf, USB_DESC_BUFSIZE,
-			function);
-	if (len < 0)
-		return len;
-	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
-	return len;
-}
-
 /* Change our operational Interface. */
-static int
-set_interface(struct printer_dev *dev, unsigned number)
+static int set_interface(struct printer_dev *dev, unsigned number)
 {
 	int			result = 0;
 
@@ -1043,14 +897,6 @@ set_interface(struct printer_dev *dev, unsigned number)
 	return result;
 }
 
-static void printer_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DBG((struct printer_dev *) ep->driver_data,
-				"setup complete --> %d, %d/%d\n",
-				req->status, req->actual, req->length);
-}
-
 static void printer_soft_reset(struct printer_dev *dev)
 {
 	struct usb_request	*req;
@@ -1107,11 +953,12 @@ static void printer_soft_reset(struct printer_dev *dev)
  * The setup() callback implements all the ep0 functionality that's not
  * handled lower down.
  */
-static int
-printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+static int printer_func_setup(struct usb_function *f,
+		const struct usb_ctrlrequest *ctrl)
 {
-	struct printer_dev	*dev = get_gadget_data(gadget);
-	struct usb_request	*req = dev->req;
+	struct printer_dev *dev = container_of(f, struct printer_dev, function);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->req;
 	int			value = -EOPNOTSUPP;
 	u16			wIndex = le16_to_cpu(ctrl->wIndex);
 	u16			wValue = le16_to_cpu(ctrl->wValue);
@@ -1120,102 +967,7 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 	DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",
 		ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);
 
-	req->complete = printer_setup_complete;
-
 	switch (ctrl->bRequestType&USB_TYPE_MASK) {
-
-	case USB_TYPE_STANDARD:
-		switch (ctrl->bRequest) {
-
-		case USB_REQ_GET_DESCRIPTOR:
-			if (ctrl->bRequestType != USB_DIR_IN)
-				break;
-			switch (wValue >> 8) {
-
-			case USB_DT_DEVICE:
-				device_desc.bMaxPacketSize0 =
-					gadget->ep0->maxpacket;
-				value = min(wLength, (u16) sizeof device_desc);
-				memcpy(req->buf, &device_desc, value);
-				break;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-			case USB_DT_DEVICE_QUALIFIER:
-				if (!gadget_is_dualspeed(gadget))
-					break;
-				/*
-				 * assumes ep0 uses the same value for both
-				 * speeds
-				 */
-				dev_qualifier.bMaxPacketSize0 =
-					gadget->ep0->maxpacket;
-				value = min(wLength,
-						(u16) sizeof dev_qualifier);
-				memcpy(req->buf, &dev_qualifier, value);
-				break;
-
-			case USB_DT_OTHER_SPEED_CONFIG:
-				if (!gadget_is_dualspeed(gadget))
-					break;
-				/* FALLTHROUGH */
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
-			case USB_DT_CONFIG:
-				value = config_buf(gadget->speed, req->buf,
-						wValue >> 8,
-						wValue & 0xff,
-						gadget->is_otg);
-				if (value >= 0)
-					value = min(wLength, (u16) value);
-				break;
-
-			case USB_DT_STRING:
-				value = usb_gadget_get_string(&stringtab,
-						wValue & 0xff, req->buf);
-				if (value >= 0)
-					value = min(wLength, (u16) value);
-				break;
-			}
-			break;
-
-		case USB_REQ_SET_CONFIGURATION:
-			if (ctrl->bRequestType != 0)
-				break;
-			if (gadget->a_hnp_support)
-				DBG(dev, "HNP available\n");
-			else if (gadget->a_alt_hnp_support)
-				DBG(dev, "HNP needs a different root port\n");
-			value = printer_set_config(dev, wValue);
-			if (!value)
-				value = set_interface(dev, PRINTER_INTERFACE);
-			break;
-		case USB_REQ_GET_CONFIGURATION:
-			if (ctrl->bRequestType != USB_DIR_IN)
-				break;
-			*(u8 *)req->buf = dev->config;
-			value = min(wLength, (u16) 1);
-			break;
-
-		case USB_REQ_SET_INTERFACE:
-			if (ctrl->bRequestType != USB_RECIP_INTERFACE ||
-					!dev->config)
-				break;
-
-			value = set_interface(dev, PRINTER_INTERFACE);
-			break;
-		case USB_REQ_GET_INTERFACE:
-			if (ctrl->bRequestType !=
-					(USB_DIR_IN|USB_RECIP_INTERFACE)
-					|| !dev->config)
-				break;
-
-			*(u8 *)req->buf = dev->interface;
-			value = min(wLength, (u16) 1);
-			break;
-
-		default:
-			goto unknown;
-		}
-		break;
-
 	case USB_TYPE_CLASS:
 		switch (ctrl->bRequest) {
 		case 0: /* Get the IEEE-1284 PNP String */
@@ -1261,44 +1013,50 @@ unknown:
 			wValue, wIndex, wLength);
 		break;
 	}
-
-	/* respond with data transfer before status phase? */
-	if (value >= 0) {
-		req->length = value;
-		req->zero = value < wLength;
-		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DBG(dev, "ep_queue --> %d\n", value);
-			req->status = 0;
-			printer_setup_complete(gadget->ep0, req);
-		}
-	}
-
 	/* host either stalls (value < 0) or reports success */
 	return value;
 }
 
-static void
-printer_disconnect(struct usb_gadget *gadget)
+static int __init printer_func_bind(struct usb_configuration *c,
+		struct usb_function *f)
 {
-	struct printer_dev	*dev = get_gadget_data(gadget);
+	return 0;
+}
+
+static void printer_func_unbind(struct usb_configuration *c,
+		struct usb_function *f)
+{
+}
+
+static int printer_func_set_alt(struct usb_function *f,
+		unsigned intf, unsigned alt)
+{
+	struct printer_dev *dev = container_of(f, struct printer_dev, function);
+	int ret = -ENOTSUPP;
+
+	if (!alt)
+		ret = set_interface(dev, PRINTER_INTERFACE);
+	return ret;
+}
+
+static void printer_func_disable(struct usb_function *f)
+{
+	struct printer_dev *dev = container_of(f, struct printer_dev, function);
 	unsigned long		flags;
 
 	DBG(dev, "%s\n", __func__);
 
 	spin_lock_irqsave(&dev->lock, flags);
-
 	printer_reset_interface(dev);
-
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
-static void
-printer_unbind(struct usb_gadget *gadget)
+static void printer_cfg_unbind(struct usb_configuration *c)
 {
-	struct printer_dev	*dev = get_gadget_data(gadget);
+	struct printer_dev	*dev;
 	struct usb_request	*req;
 
+	dev = &usb_printer_gadget;
 
 	DBG(dev, "%s\n", __func__);
 
@@ -1336,18 +1094,18 @@ printer_unbind(struct usb_gadget *gadget)
 		list_del(&req->list);
 		printer_req_free(dev->out_ep, req);
 	}
-
-	if (dev->req) {
-		printer_req_free(gadget->ep0, dev->req);
-		dev->req = NULL;
-	}
-
-	set_gadget_data(gadget, NULL);
 }
 
-static int __init
-printer_bind(struct usb_gadget *gadget)
+static struct usb_configuration printer_cfg_driver = {
+	.label			= "printer",
+	.unbind			= printer_cfg_unbind,
+	.bConfigurationValue	= 1,
+	.bmAttributes		= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+};
+
+static int __init printer_bind_config(struct usb_configuration *c)
 {
+	struct usb_gadget	*gadget = c->cdev->gadget;
 	struct printer_dev	*dev;
 	struct usb_ep		*in_ep, *out_ep;
 	int			status = -ENOMEM;
@@ -1358,6 +1116,14 @@ printer_bind(struct usb_gadget *gadget)
 
 	dev = &usb_printer_gadget;
 
+	dev->function.name = shortname;
+	dev->function.descriptors = fs_printer_function;
+	dev->function.hs_descriptors = hs_printer_function;
+	dev->function.bind = printer_func_bind;
+	dev->function.setup = printer_func_setup;
+	dev->function.unbind = printer_func_unbind;
+	dev->function.set_alt = printer_func_set_alt;
+	dev->function.disable = printer_func_disable;
 
 	/* Setup the sysfs files for the printer gadget. */
 	dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
@@ -1393,29 +1159,6 @@ printer_bind(struct usb_gadget *gadget)
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
 
-	device_desc.idVendor =
-		cpu_to_le16(PRINTER_VENDOR_NUM);
-	device_desc.idProduct =
-		cpu_to_le16(PRINTER_PRODUCT_NUM);
-
-	/* support optional vendor/distro customization */
-	if (idVendor) {
-		if (!idProduct) {
-			dev_err(&gadget->dev, "idVendor needs idProduct!\n");
-			return -ENODEV;
-		}
-		device_desc.idVendor = cpu_to_le16(idVendor);
-		device_desc.idProduct = cpu_to_le16(idProduct);
-		if (bcdDevice)
-			device_desc.bcdDevice = cpu_to_le16(bcdDevice);
-	}
-
-	if (iManufacturer)
-		strlcpy(manufacturer, iManufacturer, sizeof manufacturer);
-
-	if (iProduct)
-		strlcpy(product_desc, iProduct, sizeof product_desc);
-
 	if (iSerialNum)
 		strlcpy(serial_num, iSerialNum, sizeof serial_num);
 
@@ -1442,17 +1185,16 @@ autoconf_fail:
 		goto autoconf_fail;
 	out_ep->driver_data = out_ep;	/* claim */
 
-#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	/* assumes that all endpoints are dual-speed */
 	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
 	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
-#endif	/* DUALSPEED */
 
 	usb_gadget_set_selfpowered(gadget);
 
 	if (gadget->is_otg) {
-		otg_desc.bmAttributes |= USB_OTG_HNP,
-		config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		otg_descriptor.bmAttributes |= USB_OTG_HNP;
+		printer_cfg_driver.descriptors = otg_desc;
+		printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
 	spin_lock_init(&dev->lock);
@@ -1466,7 +1208,6 @@ autoconf_fail:
 	init_waitqueue_head(&dev->tx_wait);
 	init_waitqueue_head(&dev->tx_flush_wait);
 
-	dev->config = 0;
 	dev->interface = -1;
 	dev->printer_cdev_open = 0;
 	dev->printer_status = PRINTER_NOT_ERROR;
@@ -1477,14 +1218,6 @@ autoconf_fail:
 	dev->in_ep = in_ep;
 	dev->out_ep = out_ep;
 
-	/* preallocate control message data and buffer */
-	dev->req = printer_req_alloc(gadget->ep0, USB_DESC_BUFSIZE,
-			GFP_KERNEL);
-	if (!dev->req) {
-		status = -ENOMEM;
-		goto fail;
-	}
-
 	for (i = 0; i < QLEN; i++) {
 		req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
 		if (!req) {
@@ -1513,45 +1246,37 @@ autoconf_fail:
 		list_add(&req->list, &dev->rx_reqs);
 	}
 
-	dev->req->complete = printer_setup_complete;
-
 	/* finish hookup to lower layer ... */
 	dev->gadget = gadget;
-	set_gadget_data(gadget, dev);
-	gadget->ep0->driver_data = dev;
 
 	INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
 	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,
 			in_ep->name);
-
 	return 0;
 
 fail:
-	printer_unbind(gadget);
+	printer_cfg_unbind(c);
 	return status;
 }
 
-/*-------------------------------------------------------------------------*/
+static int printer_unbind(struct usb_composite_dev *cdev)
+{
+	return 0;
+}
 
-static struct usb_gadget_driver printer_driver = {
-	.max_speed	= DEVSPEED,
+static int __init printer_bind(struct usb_composite_dev *cdev)
+{
+	return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
+}
 
-	.function	= (char *) driver_desc,
+static struct usb_composite_driver printer_driver = {
+	.name           = shortname,
+	.dev            = &device_desc,
+	.strings        = dev_strings,
+	.max_speed      = USB_SPEED_HIGH,
 	.unbind		= printer_unbind,
-
-	.setup		= printer_setup,
-	.disconnect	= printer_disconnect,
-
-	.driver		= {
-		.name		= (char *) shortname,
-		.owner		= THIS_MODULE,
-	},
 };
 
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Craig Nadler");
-MODULE_LICENSE("GPL");
-
 static int __init
 init(void)
 {
@@ -1560,23 +1285,23 @@ init(void)
 	usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
 	if (IS_ERR(usb_gadget_class)) {
 		status = PTR_ERR(usb_gadget_class);
-		ERROR(dev, "unable to create usb_gadget class %d\n", status);
+		pr_err("unable to create usb_gadget class %d\n", status);
 		return status;
 	}
 
 	status = alloc_chrdev_region(&g_printer_devno, 0, 1,
 			"USB printer gadget");
 	if (status) {
-		ERROR(dev, "alloc_chrdev_region %d\n", status);
+		pr_err("alloc_chrdev_region %d\n", status);
 		class_destroy(usb_gadget_class);
 		return status;
 	}
 
-	status = usb_gadget_probe_driver(&printer_driver, printer_bind);
+	status = usb_composite_probe(&printer_driver, printer_bind);
 	if (status) {
 		class_destroy(usb_gadget_class);
 		unregister_chrdev_region(g_printer_devno, 1);
-		DBG(dev, "usb_gadget_probe_driver %x\n", status);
+		pr_err("usb_gadget_probe_driver %x\n", status);
 	}
 
 	return status;
@@ -1586,15 +1311,14 @@ module_init(init);
 static void __exit
 cleanup(void)
 {
-	int status;
-
 	mutex_lock(&usb_printer_gadget.lock_printer_io);
-	status = usb_gadget_unregister_driver(&printer_driver);
-	if (status)
-		ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
-
+	usb_composite_unregister(&printer_driver);
 	unregister_chrdev_region(g_printer_devno, 1);
 	class_destroy(usb_gadget_class);
 	mutex_unlock(&usb_printer_gadget.lock_printer_io);
 }
 module_exit(cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Craig Nadler");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 41ed69c96d8c..d7c8cb3bf759 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -218,7 +218,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep,
 	struct pxa25x_udc       *dev;
 
 	ep = container_of (_ep, struct pxa25x_ep, ep);
-	if (!_ep || !desc || ep->desc || _ep->name == ep0name
+	if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name
 			|| desc->bDescriptorType != USB_DT_ENDPOINT
 			|| ep->bEndpointAddress != desc->bEndpointAddress
 			|| ep->fifo_size < usb_endpoint_maxp (desc)) {
@@ -249,7 +249,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep,
 		return -ESHUTDOWN;
 	}
 
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->stopped = 0;
 	ep->pio_irqs = 0;
 	ep->ep.maxpacket = usb_endpoint_maxp (desc);
@@ -269,7 +269,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep)
 	unsigned long		flags;
 
 	ep = container_of (_ep, struct pxa25x_ep, ep);
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		DMSG("%s, %s not enabled\n", __func__,
 			_ep ? ep->ep.name : NULL);
 		return -EINVAL;
@@ -281,7 +281,6 @@ static int pxa25x_ep_disable (struct usb_ep *_ep)
 	/* flush fifo (mostly for IN buffers) */
 	pxa25x_ep_fifo_flush (_ep);
 
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
@@ -390,7 +389,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req)
 {
 	unsigned		max;
 
-	max = usb_endpoint_maxp(ep->desc);
+	max = usb_endpoint_maxp(ep->ep.desc);
 	do {
 		unsigned	count;
 		int		is_last, is_short;
@@ -644,7 +643,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	}
 
 	ep = container_of(_ep, struct pxa25x_ep, ep);
-	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+	if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
 		DMSG("%s, bad ep\n", __func__);
 		return -EINVAL;
 	}
@@ -660,7 +659,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	 * we can report per-packet status.  that also helps with dma.
 	 */
 	if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-		        && req->req.length > usb_endpoint_maxp (ep->desc)))
+			&& req->req.length > usb_endpoint_maxp(ep->ep.desc)))
 		return -EMSGSIZE;
 
 	DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
@@ -673,7 +672,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 	/* kickstart this i/o queue? */
 	if (list_empty(&ep->queue) && !ep->stopped) {
-		if (ep->desc == NULL/* ep0 */) {
+		if (ep->ep.desc == NULL/* ep0 */) {
 			unsigned	length = _req->length;
 
 			switch (dev->ep0state) {
@@ -722,7 +721,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 			req = NULL;
 		}
 
-		if (likely (req && ep->desc))
+		if (likely(req && ep->ep.desc))
 			pio_irq_enable(ep->bEndpointAddress);
 	}
 
@@ -749,7 +748,7 @@ static void nuke(struct pxa25x_ep *ep, int status)
 				queue);
 		done(ep, req, status);
 	}
-	if (ep->desc)
+	if (ep->ep.desc)
 		pio_irq_disable (ep->bEndpointAddress);
 }
 
@@ -792,7 +791,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
 
 	ep = container_of(_ep, struct pxa25x_ep, ep);
 	if (unlikely (!_ep
-			|| (!ep->desc && ep->ep.name != ep0name))
+			|| (!ep->ep.desc && ep->ep.name != ep0name))
 			|| ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
 		DMSG("%s, bad ep\n", __func__);
 		return -EINVAL;
@@ -820,7 +819,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
 	*ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF;
 
 	/* ep0 needs special care */
-	if (!ep->desc) {
+	if (!ep->ep.desc) {
 		start_watchdog(ep->dev);
 		ep->dev->req_pending = 0;
 		ep->dev->ep0state = EP0_STALL;
@@ -1087,7 +1086,7 @@ udc_seq_show(struct seq_file *m, void *_d)
 		if (i != 0) {
 			const struct usb_endpoint_descriptor	*desc;
 
-			desc = ep->desc;
+			desc = ep->ep.desc;
 			if (!desc)
 				continue;
 			tmp = *dev->ep [i].reg_udccs;
@@ -1191,7 +1190,6 @@ static void udc_reinit(struct pxa25x_udc *dev)
 		if (i != 0)
 			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
 
-		ep->desc = NULL;
 		ep->ep.desc = NULL;
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
index 893e917f048e..861f4df6ea22 100644
--- a/drivers/usb/gadget/pxa25x_udc.h
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -41,7 +41,6 @@ struct pxa25x_ep {
 	struct usb_ep				ep;
 	struct pxa25x_udc			*dev;
 
-	const struct usb_endpoint_descriptor	*desc;
 	struct list_head			queue;
 	unsigned long				pio_irqs;
 
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index c4401e7dd3a6..f3ac2a20c27c 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -459,7 +459,7 @@ static int alloc_pipe_config(struct r8a66597_ep *ep,
 	unsigned char *counter;
 	int ret;
 
-	ep->desc = desc;
+	ep->ep.desc = desc;
 
 	if (ep->pipenum)	/* already allocated pipe  */
 		return 0;
@@ -648,7 +648,7 @@ static int sudmac_alloc_channel(struct r8a66597 *r8a66597,
 	/* set SUDMAC parameters */
 	dma = &r8a66597->dma;
 	dma->used = 1;
-	if (ep->desc->bEndpointAddress & USB_DIR_IN) {
+	if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) {
 		dma->dir = 1;
 	} else {
 		dma->dir = 0;
@@ -770,7 +770,7 @@ static void start_packet_read(struct r8a66597_ep *ep,
 
 static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req)
 {
-	if (ep->desc->bEndpointAddress & USB_DIR_IN)
+	if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
 		start_packet_write(ep, req);
 	else
 		start_packet_read(ep, req);
@@ -930,7 +930,7 @@ __acquires(r8a66597->lock)
 
 	if (restart) {
 		req = get_request_from_ep(ep);
-		if (ep->desc)
+		if (ep->ep.desc)
 			start_packet(ep, req);
 	}
 }
@@ -1116,7 +1116,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb)
 				r8a66597_write(r8a66597, ~check, BRDYSTS);
 				ep = r8a66597->pipenum2ep[pipenum];
 				req = get_request_from_ep(ep);
-				if (ep->desc->bEndpointAddress & USB_DIR_IN)
+				if (ep->ep.desc->bEndpointAddress & USB_DIR_IN)
 					irq_packet_write(ep, req);
 				else
 					irq_packet_read(ep, req);
@@ -1170,7 +1170,7 @@ __acquires(r8a66597->lock)
 
 	switch (ctrl->bRequestType & USB_RECIP_MASK) {
 	case USB_RECIP_DEVICE:
-		status = 1 << USB_DEVICE_SELF_POWERED;
+		status = r8a66597->device_status;
 		break;
 	case USB_RECIP_INTERFACE:
 		status = 0;
@@ -1627,7 +1627,7 @@ static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req,
 	req->req.actual = 0;
 	req->req.status = -EINPROGRESS;
 
-	if (ep->desc == NULL)	/* control */
+	if (ep->ep.desc == NULL)	/* control */
 		start_ep0(ep, req);
 	else {
 		if (request && !ep->busy)
@@ -1692,7 +1692,7 @@ static int r8a66597_set_wedge(struct usb_ep *_ep)
 
 	ep = container_of(_ep, struct r8a66597_ep, ep);
 
-	if (!ep || !ep->desc)
+	if (!ep || !ep->ep.desc)
 		return -EINVAL;
 
 	spin_lock_irqsave(&ep->r8a66597->lock, flags);
@@ -1800,11 +1800,24 @@ static int r8a66597_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
+static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self)
+{
+	struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
+
+	if (is_self)
+		r8a66597->device_status |= 1 << USB_DEVICE_SELF_POWERED;
+	else
+		r8a66597->device_status &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+	return 0;
+}
+
 static struct usb_gadget_ops r8a66597_gadget_ops = {
 	.get_frame		= r8a66597_get_frame,
 	.udc_start		= r8a66597_start,
 	.udc_stop		= r8a66597_stop,
 	.pullup			= r8a66597_pullup,
+	.set_selfpowered	= r8a66597_set_selfpowered,
 };
 
 static int __exit r8a66597_remove(struct platform_device *pdev)
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index 8e3de61cd4b8..99908c76ccd1 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -72,7 +72,7 @@ struct r8a66597_ep {
 	unsigned		use_dma:1;
 	u16			pipenum;
 	u16			type;
-	const struct usb_endpoint_descriptor	*desc;
+
 	/* register address */
 	unsigned char		fifoaddr;
 	unsigned char		fifosel;
@@ -111,6 +111,7 @@ struct r8a66597 {
 	u16			old_vbus;
 	u16			scount;
 	u16			old_dvsq;
+	u16			device_status;	/* for GET_STATUS */
 
 	/* pipe config */
 	unsigned char bulk;
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 105b206cd844..5061a2fe9620 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -1,4 +1,5 @@
-/* linux/drivers/usb/gadget/s3c-hsotg.c
+/**
+ * linux/drivers/usb/gadget/s3c-hsotg.c
  *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
@@ -13,7 +14,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
-*/
+ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -27,21 +28,25 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
 #include <mach/map.h>
 
-#include <plat/regs-usb-hsotg-phy.h>
-#include <plat/regs-usb-hsotg.h>
-#include <mach/regs-sys.h>
-#include <plat/udc-hs.h>
-#include <plat/cpu.h>
+#include "s3c-hsotg.h"
+#include <linux/platform_data/s3c-hsotg.h>
 
 #define DMA_ADDR_INVALID (~((dma_addr_t)0))
 
-/* EP0_MPS_LIMIT
+static const char * const s3c_hsotg_supply_names[] = {
+	"vusb_d",		/* digital USB supply, 1.2V */
+	"vusb_a",		/* analog USB supply, 1.1V */
+};
+
+/*
+ * EP0_MPS_LIMIT
  *
  * Unfortunately there seems to be a limit of the amount of data that can
  * be transferred by IN transactions on EP0. This is either 127 bytes or 3
@@ -125,8 +130,6 @@ struct s3c_hsotg_ep {
 	char			name[10];
 };
 
-#define S3C_HSOTG_EPS	(8+1)	/* limit to 9 for the moment */
-
 /**
  * struct s3c_hsotg - driver state.
  * @dev: The parent device supplied to the probe function
@@ -135,7 +138,9 @@ struct s3c_hsotg_ep {
  * @regs: The memory area mapped for accessing registers.
  * @regs_res: The resource that was allocated when claiming register space.
  * @irq: The IRQ number we are using
+ * @supplies: Definition of USB power supplies
  * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
+ * @num_of_eps: Number of available EPs (excluding EP0)
  * @debug_root: root directrory for debugfs.
  * @debug_file: main status file for debugfs.
  * @debug_fifo: FIFO status file for debugfs.
@@ -143,6 +148,8 @@ struct s3c_hsotg_ep {
  * @ep0_buff: Buffer for EP0 reply data, if needed.
  * @ctrl_buff: Buffer for EP0 control requests.
  * @ctrl_req: Request for EP0 control packets.
+ * @setup: NAK management for EP0 SETUP
+ * @last_rst: Time of last reset
  * @eps: The endpoints being supplied to the gadget framework
  */
 struct s3c_hsotg {
@@ -155,7 +162,10 @@ struct s3c_hsotg {
 	int			irq;
 	struct clk		*clk;
 
+	struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+
 	unsigned int		dedicated_fifos:1;
+	unsigned char           num_of_eps;
 
 	struct dentry		*debug_root;
 	struct dentry		*debug_file;
@@ -167,7 +177,9 @@ struct s3c_hsotg {
 	u8			ctrl_buff[8];
 
 	struct usb_gadget	gadget;
-	struct s3c_hsotg_ep	eps[];
+	unsigned int		setup;
+	unsigned long           last_rst;
+	struct s3c_hsotg_ep	*eps;
 };
 
 /**
@@ -244,14 +256,14 @@ static inline bool using_dma(struct s3c_hsotg *hsotg)
  */
 static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints)
 {
-	u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK);
+	u32 gsintmsk = readl(hsotg->regs + GINTMSK);
 	u32 new_gsintmsk;
 
 	new_gsintmsk = gsintmsk | ints;
 
 	if (new_gsintmsk != gsintmsk) {
 		dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk);
-		writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK);
+		writel(new_gsintmsk, hsotg->regs + GINTMSK);
 	}
 }
 
@@ -262,13 +274,13 @@ static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints)
  */
 static void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints)
 {
-	u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK);
+	u32 gsintmsk = readl(hsotg->regs + GINTMSK);
 	u32 new_gsintmsk;
 
 	new_gsintmsk = gsintmsk & ~ints;
 
 	if (new_gsintmsk != gsintmsk)
-		writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK);
+		writel(new_gsintmsk, hsotg->regs + GINTMSK);
 }
 
 /**
@@ -293,12 +305,12 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg,
 		bit <<= 16;
 
 	local_irq_save(flags);
-	daint = readl(hsotg->regs + S3C_DAINTMSK);
+	daint = readl(hsotg->regs + DAINTMSK);
 	if (en)
 		daint |= bit;
 	else
 		daint &= ~bit;
-	writel(daint, hsotg->regs + S3C_DAINTMSK);
+	writel(daint, hsotg->regs + DAINTMSK);
 	local_irq_restore(flags);
 }
 
@@ -314,52 +326,51 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
 	int timeout;
 	u32 val;
 
-	/* the ryu 2.6.24 release ahs
-	   writel(0x1C0, hsotg->regs + S3C_GRXFSIZ);
-	   writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) |
-		S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
-		hsotg->regs + S3C_GNPTXFSIZ);
-	*/
-
 	/* set FIFO sizes to 2048/1024 */
 
-	writel(2048, hsotg->regs + S3C_GRXFSIZ);
-	writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
-	       S3C_GNPTXFSIZ_NPTxFDep(1024),
-	       hsotg->regs + S3C_GNPTXFSIZ);
+	writel(2048, hsotg->regs + GRXFSIZ);
+	writel(GNPTXFSIZ_NPTxFStAddr(2048) |
+	       GNPTXFSIZ_NPTxFDep(1024),
+	       hsotg->regs + GNPTXFSIZ);
 
-	/* arange all the rest of the TX FIFOs, as some versions of this
+	/*
+	 * arange all the rest of the TX FIFOs, as some versions of this
 	 * block have overlapping default addresses. This also ensures
 	 * that if the settings have been changed, then they are set to
-	 * known values. */
+	 * known values.
+	 */
 
 	/* start at the end of the GNPTXFSIZ, rounded up */
 	addr = 2048 + 1024;
 	size = 768;
 
-	/* currently we allocate TX FIFOs for all possible endpoints,
-	 * and assume that they are all the same size. */
+	/*
+	 * currently we allocate TX FIFOs for all possible endpoints,
+	 * and assume that they are all the same size.
+	 */
 
 	for (ep = 1; ep <= 15; ep++) {
 		val = addr;
-		val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
+		val |= size << DPTXFSIZn_DPTxFSize_SHIFT;
 		addr += size;
 
-		writel(val, hsotg->regs + S3C_DPTXFSIZn(ep));
+		writel(val, hsotg->regs + DPTXFSIZn(ep));
 	}
 
-	/* according to p428 of the design guide, we need to ensure that
-	 * all fifos are flushed before continuing */
+	/*
+	 * according to p428 of the design guide, we need to ensure that
+	 * all fifos are flushed before continuing
+	 */
 
-	writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh |
-	       S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL);
+	writel(GRSTCTL_TxFNum(0x10) | GRSTCTL_TxFFlsh |
+	       GRSTCTL_RxFFlsh, hsotg->regs + GRSTCTL);
 
 	/* wait until the fifos are both flushed */
 	timeout = 100;
 	while (1) {
-		val = readl(hsotg->regs + S3C_GRSTCTL);
+		val = readl(hsotg->regs + GRSTCTL);
 
-		if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0)
+		if ((val & (GRSTCTL_TxFFlsh | GRSTCTL_RxFFlsh)) == 0)
 			break;
 
 		if (--timeout == 0) {
@@ -415,7 +426,7 @@ static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep)
  *
  * This is the reverse of s3c_hsotg_map_dma(), called for the completion
  * of a request to ensure the buffer is ready for access by the caller.
-*/
+ */
 static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
 				struct s3c_hsotg_ep *hs_ep,
 				struct s3c_hsotg_req *hs_req)
@@ -456,13 +467,13 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
  * otherwise -ENOSPC is returned if the FIFO space was used up.
  *
  * This routine is only needed for PIO
-*/
+ */
 static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 				struct s3c_hsotg_ep *hs_ep,
 				struct s3c_hsotg_req *hs_req)
 {
 	bool periodic = is_ep_periodic(hs_ep);
-	u32 gnptxsts = readl(hsotg->regs + S3C_GNPTXSTS);
+	u32 gnptxsts = readl(hsotg->regs + GNPTXSTS);
 	int buf_pos = hs_req->req.actual;
 	int to_write = hs_ep->size_loaded;
 	void *data;
@@ -476,20 +487,23 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 		return 0;
 
 	if (periodic && !hsotg->dedicated_fifos) {
-		u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index));
+		u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
 		int size_left;
 		int size_done;
 
-		/* work out how much data was loaded so we can calculate
-		 * how much data is left in the fifo. */
+		/*
+		 * work out how much data was loaded so we can calculate
+		 * how much data is left in the fifo.
+		 */
 
-		size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+		size_left = DxEPTSIZ_XferSize_GET(epsize);
 
-		/* if shared fifo, we cannot write anything until the
+		/*
+		 * if shared fifo, we cannot write anything until the
 		 * previous data has been completely sent.
 		 */
 		if (hs_ep->fifo_load != 0) {
-			s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+			s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp);
 			return -ENOSPC;
 		}
 
@@ -510,47 +524,50 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 			__func__, can_write);
 
 		if (can_write <= 0) {
-			s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+			s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp);
 			return -ENOSPC;
 		}
 	} else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
-		can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index));
+		can_write = readl(hsotg->regs + DTXFSTS(hs_ep->index));
 
 		can_write &= 0xffff;
 		can_write *= 4;
 	} else {
-		if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
+		if (GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
 			dev_dbg(hsotg->dev,
 				"%s: no queue slots available (0x%08x)\n",
 				__func__, gnptxsts);
 
-			s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_NPTxFEmp);
+			s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTxFEmp);
 			return -ENOSPC;
 		}
 
-		can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
+		can_write = GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
 		can_write *= 4;	/* fifo size is in 32bit quantities. */
 	}
 
 	dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n",
 		 __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket);
 
-	/* limit to 512 bytes of data, it seems at least on the non-periodic
+	/*
+	 * limit to 512 bytes of data, it seems at least on the non-periodic
 	 * FIFO, requests of >512 cause the endpoint to get stuck with a
 	 * fragment of the end of the transfer in it.
 	 */
 	if (can_write > 512)
 		can_write = 512;
 
-	/* limit the write to one max-packet size worth of data, but allow
+	/*
+	 * limit the write to one max-packet size worth of data, but allow
 	 * the transfer to return that it did not run out of fifo space
-	 * doing it. */
+	 * doing it.
+	 */
 	if (to_write > hs_ep->ep.maxpacket) {
 		to_write = hs_ep->ep.maxpacket;
 
 		s3c_hsotg_en_gsint(hsotg,
-				   periodic ? S3C_GINTSTS_PTxFEmp :
-				   S3C_GINTSTS_NPTxFEmp);
+				   periodic ? GINTSTS_PTxFEmp :
+				   GINTSTS_NPTxFEmp);
 	}
 
 	/* see if we can write data */
@@ -559,8 +576,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 		to_write = can_write;
 		pkt_round = to_write % hs_ep->ep.maxpacket;
 
-		/* Not sure, but we probably shouldn't be writing partial
-		 * packets into the FIFO, so round the write down to an
+		/*
+		 * Round the write down to an
 		 * exact number of packets.
 		 *
 		 * Note, we do not currently check to see if we can ever
@@ -570,12 +587,14 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 		if (pkt_round)
 			to_write -= pkt_round;
 
-		/* enable correct FIFO interrupt to alert us when there
-		 * is more room left. */
+		/*
+		 * enable correct FIFO interrupt to alert us when there
+		 * is more room left.
+		 */
 
 		s3c_hsotg_en_gsint(hsotg,
-				   periodic ? S3C_GINTSTS_PTxFEmp :
-				   S3C_GINTSTS_NPTxFEmp);
+				   periodic ? GINTSTS_PTxFEmp :
+				   GINTSTS_NPTxFEmp);
 	}
 
 	dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n",
@@ -593,7 +612,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 	to_write = DIV_ROUND_UP(to_write, 4);
 	data = hs_req->req.buf + buf_pos;
 
-	writesl(hsotg->regs + S3C_EPFIFO(hs_ep->index), data, to_write);
+	writesl(hsotg->regs + EPFIFO(hs_ep->index), data, to_write);
 
 	return (to_write >= can_write) ? -ENOSPC : 0;
 }
@@ -612,12 +631,12 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
 	unsigned maxpkt;
 
 	if (index != 0) {
-		maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1;
-		maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1;
+		maxsize = DxEPTSIZ_XferSize_LIMIT + 1;
+		maxpkt = DxEPTSIZ_PktCnt_LIMIT + 1;
 	} else {
 		maxsize = 64+64;
 		if (hs_ep->dir_in)
-			maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1;
+			maxpkt = DIEPTSIZ0_PktCnt_LIMIT + 1;
 		else
 			maxpkt = 2;
 	}
@@ -626,8 +645,10 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
 	maxpkt--;
 	maxsize--;
 
-	/* constrain by packet count if maxpkts*pktsize is greater
-	 * than the length register size. */
+	/*
+	 * constrain by packet count if maxpkts*pktsize is greater
+	 * than the length register size.
+	 */
 
 	if ((maxpkt * hs_ep->ep.maxpacket) < maxsize)
 		maxsize = maxpkt * hs_ep->ep.maxpacket;
@@ -674,8 +695,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
 		}
 	}
 
-	epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index);
-	epsize_reg = dir_in ? S3C_DIEPTSIZ(index) : S3C_DOEPTSIZ(index);
+	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
+	epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index);
 
 	dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n",
 		__func__, readl(hsotg->regs + epctrl_reg), index,
@@ -684,13 +705,14 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
 	/* If endpoint is stalled, we will restart request later */
 	ctrl = readl(hsotg->regs + epctrl_reg);
 
-	if (ctrl & S3C_DxEPCTL_Stall) {
+	if (ctrl & DxEPCTL_Stall) {
 		dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
 		return;
 	}
 
 	length = ureq->length - ureq->actual;
-
+	dev_dbg(hsotg->dev, "ureq->length:%d ureq->actual:%d\n",
+		ureq->length, ureq->actual);
 	if (0)
 		dev_dbg(hsotg->dev,
 			"REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n",
@@ -717,20 +739,22 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
 		packets = 1;	/* send one packet if length is zero. */
 
 	if (dir_in && index != 0)
-		epsize = S3C_DxEPTSIZ_MC(1);
+		epsize = DxEPTSIZ_MC(1);
 	else
 		epsize = 0;
 
 	if (index != 0 && ureq->zero) {
-		/* test for the packets being exactly right for the
-		 * transfer */
+		/*
+		 * test for the packets being exactly right for the
+		 * transfer
+		 */
 
 		if (length == (packets * hs_ep->ep.maxpacket))
 			packets++;
 	}
 
-	epsize |= S3C_DxEPTSIZ_PktCnt(packets);
-	epsize |= S3C_DxEPTSIZ_XferSize(length);
+	epsize |= DxEPTSIZ_PktCnt(packets);
+	epsize |= DxEPTSIZ_XferSize(length);
 
 	dev_dbg(hsotg->dev, "%s: %d@%d/%d, 0x%08x => 0x%08x\n",
 		__func__, packets, length, ureq->length, epsize, epsize_reg);
@@ -744,26 +768,38 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
 	if (using_dma(hsotg) && !continuing) {
 		unsigned int dma_reg;
 
-		/* write DMA address to control register, buffer already
-		 * synced by s3c_hsotg_ep_queue().  */
+		/*
+		 * write DMA address to control register, buffer already
+		 * synced by s3c_hsotg_ep_queue().
+		 */
 
-		dma_reg = dir_in ? S3C_DIEPDMA(index) : S3C_DOEPDMA(index);
+		dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index);
 		writel(ureq->dma, hsotg->regs + dma_reg);
 
 		dev_dbg(hsotg->dev, "%s: 0x%08x => 0x%08x\n",
 			__func__, ureq->dma, dma_reg);
 	}
 
-	ctrl |= S3C_DxEPCTL_EPEna;	/* ensure ep enabled */
-	ctrl |= S3C_DxEPCTL_USBActEp;
-	ctrl |= S3C_DxEPCTL_CNAK;	/* clear NAK set by core */
+	ctrl |= DxEPCTL_EPEna;	/* ensure ep enabled */
+	ctrl |= DxEPCTL_USBActEp;
+
+	dev_dbg(hsotg->dev, "setup req:%d\n", hsotg->setup);
+
+	/* For Setup request do not clear NAK */
+	if (hsotg->setup && index == 0)
+		hsotg->setup = 0;
+	else
+		ctrl |= DxEPCTL_CNAK;	/* clear NAK set by core */
+
 
 	dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
 	writel(ctrl, hsotg->regs + epctrl_reg);
 
-	/* set these, it seems that DMA support increments past the end
+	/*
+	 * set these, it seems that DMA support increments past the end
 	 * of the packet buffer so we need to calculate the length from
-	 * this information. */
+	 * this information.
+	 */
 	hs_ep->size_loaded = length;
 	hs_ep->last_load = ureq->actual;
 
@@ -774,17 +810,21 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
 		s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req);
 	}
 
-	/* clear the INTknTXFEmpMsk when we start request, more as a aide
-	 * to debugging to see what is going on. */
+	/*
+	 * clear the INTknTXFEmpMsk when we start request, more as a aide
+	 * to debugging to see what is going on.
+	 */
 	if (dir_in)
-		writel(S3C_DIEPMSK_INTknTXFEmpMsk,
-		       hsotg->regs + S3C_DIEPINT(index));
+		writel(DIEPMSK_INTknTXFEmpMsk,
+		       hsotg->regs + DIEPINT(index));
 
-	/* Note, trying to clear the NAK here causes problems with transmit
-	 * on the S3C6400 ending up with the TXFIFO becoming full. */
+	/*
+	 * Note, trying to clear the NAK here causes problems with transmit
+	 * on the S3C6400 ending up with the TXFIFO becoming full.
+	 */
 
 	/* check ep is enabled */
-	if (!(readl(hsotg->regs + epctrl_reg) & S3C_DxEPCTL_EPEna))
+	if (!(readl(hsotg->regs + epctrl_reg) & DxEPCTL_EPEna))
 		dev_warn(hsotg->dev,
 			 "ep%d: failed to become enabled (DxEPCTL=0x%08x)?\n",
 			 index, readl(hsotg->regs + epctrl_reg));
@@ -804,7 +844,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
  * then ensure the buffer has been synced to memory. If our buffer has no
  * DMA memory, then we map the memory and mark our request to allow us to
  * cleanup on completion.
-*/
+ */
 static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
 			     struct s3c_hsotg_ep *hs_ep,
 			     struct usb_request *req)
@@ -922,7 +962,7 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
  *
  * Convert the given wIndex into a pointer to an driver endpoint
  * structure, or return NULL if it is not a valid endpoint.
-*/
+ */
 static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg,
 					   u32 windex)
 {
@@ -933,7 +973,7 @@ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg,
 	if (windex >= 0x100)
 		return NULL;
 
-	if (idx > S3C_HSOTG_EPS)
+	if (idx > hsotg->num_of_eps)
 		return NULL;
 
 	if (idx && ep->dir_in != dir)
@@ -1151,24 +1191,28 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
 		 ctrl->bRequest, ctrl->bRequestType,
 		 ctrl->wValue, ctrl->wLength);
 
-	/* record the direction of the request, for later use when enquing
-	 * packets onto EP0. */
+	/*
+	 * record the direction of the request, for later use when enquing
+	 * packets onto EP0.
+	 */
 
 	ep0->dir_in = (ctrl->bRequestType & USB_DIR_IN) ? 1 : 0;
 	dev_dbg(hsotg->dev, "ctrl: dir_in=%d\n", ep0->dir_in);
 
-	/* if we've no data with this request, then the last part of the
-	 * transaction is going to implicitly be IN. */
+	/*
+	 * if we've no data with this request, then the last part of the
+	 * transaction is going to implicitly be IN.
+	 */
 	if (ctrl->wLength == 0)
 		ep0->dir_in = 1;
 
 	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
 		switch (ctrl->bRequest) {
 		case USB_REQ_SET_ADDRESS:
-			dcfg = readl(hsotg->regs + S3C_DCFG);
-			dcfg &= ~S3C_DCFG_DevAddr_MASK;
-			dcfg |= ctrl->wValue << S3C_DCFG_DevAddr_SHIFT;
-			writel(dcfg, hsotg->regs + S3C_DCFG);
+			dcfg = readl(hsotg->regs + DCFG);
+			dcfg &= ~DCFG_DevAddr_MASK;
+			dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT;
+			writel(dcfg, hsotg->regs + DCFG);
 
 			dev_info(hsotg->dev, "new address %d\n", ctrl->wValue);
 
@@ -1194,7 +1238,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
 			dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);
 	}
 
-	/* the request is either unhandlable, or is not formatted correctly
+	/*
+	 * the request is either unhandlable, or is not formatted correctly
 	 * so respond with a STALL for the status stage to indicate failure.
 	 */
 
@@ -1203,22 +1248,26 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
 		u32 ctrl;
 
 		dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
-		reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0;
+		reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;
 
-		/* S3C_DxEPCTL_Stall will be cleared by EP once it has
-		 * taken effect, so no need to clear later. */
+		/*
+		 * DxEPCTL_Stall will be cleared by EP once it has
+		 * taken effect, so no need to clear later.
+		 */
 
 		ctrl = readl(hsotg->regs + reg);
-		ctrl |= S3C_DxEPCTL_Stall;
-		ctrl |= S3C_DxEPCTL_CNAK;
+		ctrl |= DxEPCTL_Stall;
+		ctrl |= DxEPCTL_CNAK;
 		writel(ctrl, hsotg->regs + reg);
 
 		dev_dbg(hsotg->dev,
 			"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
 			ctrl, reg, readl(hsotg->regs + reg));
 
-		/* don't believe we need to anything more to get the EP
-		 * to reply with a STALL packet */
+		/*
+		 * don't believe we need to anything more to get the EP
+		 * to reply with a STALL packet
+		 */
 	}
 }
 
@@ -1279,8 +1328,10 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg)
 	ret = s3c_hsotg_ep_queue(&hsotg->eps[0].ep, req, GFP_ATOMIC);
 	if (ret < 0) {
 		dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret);
-		/* Don't think there's much we can do other than watch the
-		 * driver fail. */
+		/*
+		 * Don't think there's much we can do other than watch the
+		 * driver fail.
+		 */
 	}
 }
 
@@ -1296,7 +1347,7 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg)
  * on the endpoint.
  *
  * Note, expects the ep to already be locked as appropriate.
-*/
+ */
 static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
 				       struct s3c_hsotg_ep *hs_ep,
 				       struct s3c_hsotg_req *hs_req,
@@ -1312,8 +1363,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
 	dev_dbg(hsotg->dev, "complete: ep %p %s, req %p, %d => %p\n",
 		hs_ep, hs_ep->ep.name, hs_req, result, hs_req->req.complete);
 
-	/* only replace the status if we've not already set an error
-	 * from a previous transaction */
+	/*
+	 * only replace the status if we've not already set an error
+	 * from a previous transaction
+	 */
 
 	if (hs_req->req.status == -EINPROGRESS)
 		hs_req->req.status = result;
@@ -1324,8 +1377,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
 	if (using_dma(hsotg))
 		s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
 
-	/* call the complete request with the locks off, just in case the
-	 * request tries to queue more work for this endpoint. */
+	/*
+	 * call the complete request with the locks off, just in case the
+	 * request tries to queue more work for this endpoint.
+	 */
 
 	if (hs_req->req.complete) {
 		spin_unlock(&hs_ep->lock);
@@ -1333,9 +1388,11 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
 		spin_lock(&hs_ep->lock);
 	}
 
-	/* Look to see if there is anything else to do. Note, the completion
+	/*
+	 * Look to see if there is anything else to do. Note, the completion
 	 * of the previous request may have caused a new request to be started
-	 * so be careful when doing this. */
+	 * so be careful when doing this.
+	 */
 
 	if (!hs_ep->req && result >= 0) {
 		restart = !list_empty(&hs_ep->queue);
@@ -1355,7 +1412,7 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
  *
  * See s3c_hsotg_complete_request(), but called with the endpoint's
  * lock held.
-*/
+ */
 static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg,
 					    struct s3c_hsotg_ep *hs_ep,
 					    struct s3c_hsotg_req *hs_req,
@@ -1382,13 +1439,13 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
 {
 	struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep_idx];
 	struct s3c_hsotg_req *hs_req = hs_ep->req;
-	void __iomem *fifo = hsotg->regs + S3C_EPFIFO(ep_idx);
+	void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx);
 	int to_read;
 	int max_req;
 	int read_ptr;
 
 	if (!hs_req) {
-		u32 epctl = readl(hsotg->regs + S3C_DOEPCTL(ep_idx));
+		u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
 		int ptr;
 
 		dev_warn(hsotg->dev,
@@ -1412,7 +1469,8 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
 		__func__, to_read, max_req, read_ptr, hs_req->req.length);
 
 	if (to_read > max_req) {
-		/* more data appeared than we where willing
+		/*
+		 * more data appeared than we where willing
 		 * to deal with in this request.
 		 */
 
@@ -1424,8 +1482,10 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
 	hs_req->req.actual += to_read;
 	to_read = DIV_ROUND_UP(to_read, 4);
 
-	/* note, we might over-write the buffer end by 3 bytes depending on
-	 * alignment of the data. */
+	/*
+	 * note, we might over-write the buffer end by 3 bytes depending on
+	 * alignment of the data.
+	 */
 	readsl(fifo, hs_req->req.buf + read_ptr, to_read);
 
 	spin_unlock(&hs_ep->lock);
@@ -1465,14 +1525,14 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
 	dev_dbg(hsotg->dev, "sending zero-length packet\n");
 
 	/* issue a zero-sized packet to terminate this */
-	writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |
-	       S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0));
+	writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) |
+	       DxEPTSIZ_XferSize(0), hsotg->regs + DIEPTSIZ(0));
 
-	ctrl = readl(hsotg->regs + S3C_DIEPCTL0);
-	ctrl |= S3C_DxEPCTL_CNAK;  /* clear NAK set by core */
-	ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */
-	ctrl |= S3C_DxEPCTL_USBActEp;
-	writel(ctrl, hsotg->regs + S3C_DIEPCTL0);
+	ctrl = readl(hsotg->regs + DIEPCTL0);
+	ctrl |= DxEPCTL_CNAK;  /* clear NAK set by core */
+	ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */
+	ctrl |= DxEPCTL_USBActEp;
+	writel(ctrl, hsotg->regs + DIEPCTL0);
 }
 
 /**
@@ -1484,15 +1544,15 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
  * The RXFIFO has delivered an OutDone event, which means that the data
  * transfer for an OUT endpoint has been completed, either by a short
  * packet or by the finish of a transfer.
-*/
+ */
 static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
 				     int epnum, bool was_setup)
 {
-	u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
+	u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum));
 	struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum];
 	struct s3c_hsotg_req *hs_req = hs_ep->req;
 	struct usb_request *req = &hs_req->req;
-	unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+	unsigned size_left = DxEPTSIZ_XferSize_GET(epsize);
 	int result = 0;
 
 	if (!hs_req) {
@@ -1503,7 +1563,8 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
 	if (using_dma(hsotg)) {
 		unsigned size_done;
 
-		/* Calculate the size of the transfer by checking how much
+		/*
+		 * Calculate the size of the transfer by checking how much
 		 * is left in the endpoint size register and then working it
 		 * out from the amount we loaded for the transfer.
 		 *
@@ -1521,17 +1582,29 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
 	if (req->actual < req->length && size_left == 0) {
 		s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
 		return;
+	} else if (epnum == 0) {
+		/*
+		 * After was_setup = 1 =>
+		 * set CNAK for non Setup requests
+		 */
+		hsotg->setup = was_setup ? 0 : 1;
 	}
 
 	if (req->actual < req->length && req->short_not_ok) {
 		dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n",
 			__func__, req->actual, req->length);
 
-		/* todo - what should we return here? there's no one else
-		 * even bothering to check the status. */
+		/*
+		 * todo - what should we return here? there's no one else
+		 * even bothering to check the status.
+		 */
 	}
 
 	if (epnum == 0) {
+		/*
+		 * Condition req->complete != s3c_hsotg_complete_setup says:
+		 * send ZLP when we have an asynchronous request from gadget
+		 */
 		if (!was_setup && req->complete != s3c_hsotg_complete_setup)
 			s3c_hsotg_send_zlp(hsotg, hs_req);
 	}
@@ -1544,14 +1617,14 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
  * @hsotg: The device instance
  *
  * Return the current frame number
-*/
+ */
 static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg)
 {
 	u32 dsts;
 
-	dsts = readl(hsotg->regs + S3C_DSTS);
-	dsts &= S3C_DSTS_SOFFN_MASK;
-	dsts >>= S3C_DSTS_SOFFN_SHIFT;
+	dsts = readl(hsotg->regs + DSTS);
+	dsts &= DSTS_SOFFN_MASK;
+	dsts >>= DSTS_SOFFN_SHIFT;
 
 	return dsts;
 }
@@ -1574,29 +1647,29 @@ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg)
  */
 static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
 {
-	u32 grxstsr = readl(hsotg->regs + S3C_GRXSTSP);
+	u32 grxstsr = readl(hsotg->regs + GRXSTSP);
 	u32 epnum, status, size;
 
 	WARN_ON(using_dma(hsotg));
 
-	epnum = grxstsr & S3C_GRXSTS_EPNum_MASK;
-	status = grxstsr & S3C_GRXSTS_PktSts_MASK;
+	epnum = grxstsr & GRXSTS_EPNum_MASK;
+	status = grxstsr & GRXSTS_PktSts_MASK;
 
-	size = grxstsr & S3C_GRXSTS_ByteCnt_MASK;
-	size >>= S3C_GRXSTS_ByteCnt_SHIFT;
+	size = grxstsr & GRXSTS_ByteCnt_MASK;
+	size >>= GRXSTS_ByteCnt_SHIFT;
 
 	if (1)
 		dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n",
 			__func__, grxstsr, size, epnum);
 
-#define __status(x) ((x) >> S3C_GRXSTS_PktSts_SHIFT)
+#define __status(x) ((x) >> GRXSTS_PktSts_SHIFT)
 
-	switch (status >> S3C_GRXSTS_PktSts_SHIFT) {
-	case __status(S3C_GRXSTS_PktSts_GlobalOutNAK):
+	switch (status >> GRXSTS_PktSts_SHIFT) {
+	case __status(GRXSTS_PktSts_GlobalOutNAK):
 		dev_dbg(hsotg->dev, "GlobalOutNAK\n");
 		break;
 
-	case __status(S3C_GRXSTS_PktSts_OutDone):
+	case __status(GRXSTS_PktSts_OutDone):
 		dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n",
 			s3c_hsotg_read_frameno(hsotg));
 
@@ -1604,24 +1677,24 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
 			s3c_hsotg_handle_outdone(hsotg, epnum, false);
 		break;
 
-	case __status(S3C_GRXSTS_PktSts_SetupDone):
+	case __status(GRXSTS_PktSts_SetupDone):
 		dev_dbg(hsotg->dev,
 			"SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
 			s3c_hsotg_read_frameno(hsotg),
-			readl(hsotg->regs + S3C_DOEPCTL(0)));
+			readl(hsotg->regs + DOEPCTL(0)));
 
 		s3c_hsotg_handle_outdone(hsotg, epnum, true);
 		break;
 
-	case __status(S3C_GRXSTS_PktSts_OutRX):
+	case __status(GRXSTS_PktSts_OutRX):
 		s3c_hsotg_rx_data(hsotg, epnum, size);
 		break;
 
-	case __status(S3C_GRXSTS_PktSts_SetupRX):
+	case __status(GRXSTS_PktSts_SetupRX):
 		dev_dbg(hsotg->dev,
 			"SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
 			s3c_hsotg_read_frameno(hsotg),
-			readl(hsotg->regs + S3C_DOEPCTL(0)));
+			readl(hsotg->regs + DOEPCTL(0)));
 
 		s3c_hsotg_rx_data(hsotg, epnum, size);
 		break;
@@ -1638,18 +1711,18 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
 /**
  * s3c_hsotg_ep0_mps - turn max packet size into register setting
  * @mps: The maximum packet size in bytes.
-*/
+ */
 static u32 s3c_hsotg_ep0_mps(unsigned int mps)
 {
 	switch (mps) {
 	case 64:
-		return S3C_D0EPCTL_MPS_64;
+		return D0EPCTL_MPS_64;
 	case 32:
-		return S3C_D0EPCTL_MPS_32;
+		return D0EPCTL_MPS_32;
 	case 16:
-		return S3C_D0EPCTL_MPS_16;
+		return D0EPCTL_MPS_16;
 	case 8:
-		return S3C_D0EPCTL_MPS_8;
+		return D0EPCTL_MPS_8;
 	}
 
 	/* bad max packet size, warn and return invalid result */
@@ -1680,7 +1753,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
 		if (mpsval > 3)
 			goto bad_mps;
 	} else {
-		if (mps >= S3C_DxEPCTL_MPS_LIMIT+1)
+		if (mps >= DxEPCTL_MPS_LIMIT+1)
 			goto bad_mps;
 
 		mpsval = mps;
@@ -1688,19 +1761,21 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
 
 	hs_ep->ep.maxpacket = mps;
 
-	/* update both the in and out endpoint controldir_ registers, even
-	 * if one of the directions may not be in use. */
+	/*
+	 * update both the in and out endpoint controldir_ registers, even
+	 * if one of the directions may not be in use.
+	 */
 
-	reg = readl(regs + S3C_DIEPCTL(ep));
-	reg &= ~S3C_DxEPCTL_MPS_MASK;
+	reg = readl(regs + DIEPCTL(ep));
+	reg &= ~DxEPCTL_MPS_MASK;
 	reg |= mpsval;
-	writel(reg, regs + S3C_DIEPCTL(ep));
+	writel(reg, regs + DIEPCTL(ep));
 
 	if (ep) {
-		reg = readl(regs + S3C_DOEPCTL(ep));
-		reg &= ~S3C_DxEPCTL_MPS_MASK;
+		reg = readl(regs + DOEPCTL(ep));
+		reg &= ~DxEPCTL_MPS_MASK;
 		reg |= mpsval;
-		writel(reg, regs + S3C_DOEPCTL(ep));
+		writel(reg, regs + DOEPCTL(ep));
 	}
 
 	return;
@@ -1719,16 +1794,16 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
 	int timeout;
 	int val;
 
-	writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh,
-		hsotg->regs + S3C_GRSTCTL);
+	writel(GRSTCTL_TxFNum(idx) | GRSTCTL_TxFFlsh,
+		hsotg->regs + GRSTCTL);
 
 	/* wait until the fifo is flushed */
 	timeout = 100;
 
 	while (1) {
-		val = readl(hsotg->regs + S3C_GRSTCTL);
+		val = readl(hsotg->regs + GRSTCTL);
 
-		if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0)
+		if ((val & (GRSTCTL_TxFFlsh)) == 0)
 			break;
 
 		if (--timeout == 0) {
@@ -1778,7 +1853,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
 				  struct s3c_hsotg_ep *hs_ep)
 {
 	struct s3c_hsotg_req *hs_req = hs_ep->req;
-	u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index));
+	u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
 	int size_left, size_done;
 
 	if (!hs_req) {
@@ -1786,7 +1861,15 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
 		return;
 	}
 
-	/* Calculate the size of the transfer by checking how much is left
+	/* Finish ZLP handling for IN EP0 transactions */
+	if (hsotg->eps[0].sent_zlp) {
+		dev_dbg(hsotg->dev, "zlp packet received\n");
+		s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0);
+		return;
+	}
+
+	/*
+	 * Calculate the size of the transfer by checking how much is left
 	 * in the endpoint size register and then working it out from
 	 * the amount we loaded for the transfer.
 	 *
@@ -1795,7 +1878,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
 	 * aligned).
 	 */
 
-	size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
+	size_left = DxEPTSIZ_XferSize_GET(epsize);
 
 	size_done = hs_ep->size_loaded - size_left;
 	size_done += hs_ep->last_load;
@@ -1805,9 +1888,28 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
 			__func__, hs_req->req.actual, size_done);
 
 	hs_req->req.actual = size_done;
+	dev_dbg(hsotg->dev, "req->length:%d req->actual:%d req->zero:%d\n",
+		hs_req->req.length, hs_req->req.actual, hs_req->req.zero);
 
-	/* if we did all of the transfer, and there is more data left
-	 * around, then try restarting the rest of the request */
+	/*
+	 * Check if dealing with Maximum Packet Size(MPS) IN transfer at EP0
+	 * When sent data is a multiple MPS size (e.g. 64B ,128B ,192B
+	 * ,256B ... ), after last MPS sized packet send IN ZLP packet to
+	 * inform the host that no more data is available.
+	 * The state of req.zero member is checked to be sure that the value to
+	 * send is smaller than wValue expected from host.
+	 * Check req.length to NOT send another ZLP when the current one is
+	 * under completion (the one for which this completion has been called).
+	 */
+	if (hs_req->req.length && hs_ep->index == 0 && hs_req->req.zero &&
+	    hs_req->req.length == hs_req->req.actual &&
+	    !(hs_req->req.length % hs_ep->ep.maxpacket)) {
+
+		dev_dbg(hsotg->dev, "ep0 zlp IN packet sent\n");
+		s3c_hsotg_send_zlp(hsotg, hs_req);
+
+		return;
+	}
 
 	if (!size_left && hs_req->req.actual < hs_req->req.length) {
 		dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__);
@@ -1823,14 +1925,14 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
  * @dir_in: Set if this is an IN endpoint
  *
  * Process and clear any interrupt pending for an individual endpoint
-*/
+ */
 static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
 			    int dir_in)
 {
 	struct s3c_hsotg_ep *hs_ep = &hsotg->eps[idx];
-	u32 epint_reg = dir_in ? S3C_DIEPINT(idx) : S3C_DOEPINT(idx);
-	u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx);
-	u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx);
+	u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx);
+	u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx);
+	u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx);
 	u32 ints;
 
 	ints = readl(hsotg->regs + epint_reg);
@@ -1841,28 +1943,32 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
 	dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n",
 		__func__, idx, dir_in ? "in" : "out", ints);
 
-	if (ints & S3C_DxEPINT_XferCompl) {
+	if (ints & DxEPINT_XferCompl) {
 		dev_dbg(hsotg->dev,
 			"%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n",
 			__func__, readl(hsotg->regs + epctl_reg),
 			readl(hsotg->regs + epsiz_reg));
 
-		/* we get OutDone from the FIFO, so we only need to look
-		 * at completing IN requests here */
+		/*
+		 * we get OutDone from the FIFO, so we only need to look
+		 * at completing IN requests here
+		 */
 		if (dir_in) {
 			s3c_hsotg_complete_in(hsotg, hs_ep);
 
 			if (idx == 0 && !hs_ep->req)
 				s3c_hsotg_enqueue_setup(hsotg);
 		} else if (using_dma(hsotg)) {
-			/* We're using DMA, we need to fire an OutDone here
-			 * as we ignore the RXFIFO. */
+			/*
+			 * We're using DMA, we need to fire an OutDone here
+			 * as we ignore the RXFIFO.
+			 */
 
 			s3c_hsotg_handle_outdone(hsotg, idx, false);
 		}
 	}
 
-	if (ints & S3C_DxEPINT_EPDisbld) {
+	if (ints & DxEPINT_EPDisbld) {
 		dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
 
 		if (dir_in) {
@@ -1870,27 +1976,29 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
 
 			s3c_hsotg_txfifo_flush(hsotg, idx);
 
-			if ((epctl & S3C_DxEPCTL_Stall) &&
-				(epctl & S3C_DxEPCTL_EPType_Bulk)) {
-				int dctl = readl(hsotg->regs + S3C_DCTL);
+			if ((epctl & DxEPCTL_Stall) &&
+				(epctl & DxEPCTL_EPType_Bulk)) {
+				int dctl = readl(hsotg->regs + DCTL);
 
-				dctl |= S3C_DCTL_CGNPInNAK;
-				writel(dctl, hsotg->regs + S3C_DCTL);
+				dctl |= DCTL_CGNPInNAK;
+				writel(dctl, hsotg->regs + DCTL);
 			}
 		}
 	}
 
-	if (ints & S3C_DxEPINT_AHBErr)
+	if (ints & DxEPINT_AHBErr)
 		dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__);
 
-	if (ints & S3C_DxEPINT_Setup) {  /* Setup or Timeout */
+	if (ints & DxEPINT_Setup) {  /* Setup or Timeout */
 		dev_dbg(hsotg->dev, "%s: Setup/Timeout\n",  __func__);
 
 		if (using_dma(hsotg) && idx == 0) {
-			/* this is the notification we've received a
+			/*
+			 * this is the notification we've received a
 			 * setup packet. In non-DMA mode we'd get this
 			 * from the RXFIFO, instead we need to process
-			 * the setup here. */
+			 * the setup here.
+			 */
 
 			if (dir_in)
 				WARN_ON_ONCE(1);
@@ -1899,26 +2007,25 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
 		}
 	}
 
-	if (ints & S3C_DxEPINT_Back2BackSetup)
+	if (ints & DxEPINT_Back2BackSetup)
 		dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__);
 
 	if (dir_in) {
-		/* not sure if this is important, but we'll clear it anyway
-		 */
-		if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) {
+		/* not sure if this is important, but we'll clear it anyway */
+		if (ints & DIEPMSK_INTknTXFEmpMsk) {
 			dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n",
 				__func__, idx);
 		}
 
 		/* this probably means something bad is happening */
-		if (ints & S3C_DIEPMSK_INTknEPMisMsk) {
+		if (ints & DIEPMSK_INTknEPMisMsk) {
 			dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n",
 				 __func__, idx);
 		}
 
 		/* FIFO has space or is empty (see GAHBCFG) */
 		if (hsotg->dedicated_fifos &&
-		    ints & S3C_DIEPMSK_TxFIFOEmpty) {
+		    ints & DIEPMSK_TxFIFOEmpty) {
 			dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
 				__func__, idx);
 			if (!using_dma(hsotg))
@@ -1933,40 +2040,45 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
  *
  * Handle updating the device settings after the enumeration phase has
  * been completed.
-*/
+ */
 static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
 {
-	u32 dsts = readl(hsotg->regs + S3C_DSTS);
+	u32 dsts = readl(hsotg->regs + DSTS);
 	int ep0_mps = 0, ep_mps;
 
-	/* This should signal the finish of the enumeration phase
+	/*
+	 * This should signal the finish of the enumeration phase
 	 * of the USB handshaking, so we should now know what rate
-	 * we connected at. */
+	 * we connected at.
+	 */
 
 	dev_dbg(hsotg->dev, "EnumDone (DSTS=0x%08x)\n", dsts);
 
-	/* note, since we're limited by the size of transfer on EP0, and
+	/*
+	 * note, since we're limited by the size of transfer on EP0, and
 	 * it seems IN transfers must be a even number of packets we do
-	 * not advertise a 64byte MPS on EP0. */
+	 * not advertise a 64byte MPS on EP0.
+	 */
 
 	/* catch both EnumSpd_FS and EnumSpd_FS48 */
-	switch (dsts & S3C_DSTS_EnumSpd_MASK) {
-	case S3C_DSTS_EnumSpd_FS:
-	case S3C_DSTS_EnumSpd_FS48:
+	switch (dsts & DSTS_EnumSpd_MASK) {
+	case DSTS_EnumSpd_FS:
+	case DSTS_EnumSpd_FS48:
 		hsotg->gadget.speed = USB_SPEED_FULL;
 		ep0_mps = EP0_MPS_LIMIT;
 		ep_mps = 64;
 		break;
 
-	case S3C_DSTS_EnumSpd_HS:
+	case DSTS_EnumSpd_HS:
 		hsotg->gadget.speed = USB_SPEED_HIGH;
 		ep0_mps = EP0_MPS_LIMIT;
 		ep_mps = 512;
 		break;
 
-	case S3C_DSTS_EnumSpd_LS:
+	case DSTS_EnumSpd_LS:
 		hsotg->gadget.speed = USB_SPEED_LOW;
-		/* note, we don't actually support LS in this driver at the
+		/*
+		 * note, we don't actually support LS in this driver at the
 		 * moment, and the documentation seems to imply that it isn't
 		 * supported by the PHYs on some of the devices.
 		 */
@@ -1975,13 +2087,15 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
 	dev_info(hsotg->dev, "new device is %s\n",
 		 usb_speed_string(hsotg->gadget.speed));
 
-	/* we should now know the maximum packet size for an
-	 * endpoint, so set the endpoints to a default value. */
+	/*
+	 * we should now know the maximum packet size for an
+	 * endpoint, so set the endpoints to a default value.
+	 */
 
 	if (ep0_mps) {
 		int i;
 		s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps);
-		for (i = 1; i < S3C_HSOTG_EPS; i++)
+		for (i = 1; i < hsotg->num_of_eps; i++)
 			s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps);
 	}
 
@@ -1990,8 +2104,8 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
 	s3c_hsotg_enqueue_setup(hsotg);
 
 	dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-		readl(hsotg->regs + S3C_DIEPCTL0),
-		readl(hsotg->regs + S3C_DOEPCTL0));
+		readl(hsotg->regs + DIEPCTL0),
+		readl(hsotg->regs + DOEPCTL0));
 }
 
 /**
@@ -2014,8 +2128,10 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
 	spin_lock_irqsave(&ep->lock, flags);
 
 	list_for_each_entry_safe(req, treq, &ep->queue, queue) {
-		/* currently, we can't do much about an already
-		 * running request on an in endpoint */
+		/*
+		 * currently, we can't do much about an already
+		 * running request on an in endpoint
+		 */
 
 		if (ep->req == req && ep->dir_in && !force)
 			continue;
@@ -2033,18 +2149,18 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
 		(_hs)->driver->_entry(&(_hs)->gadget);
 
 /**
- * s3c_hsotg_disconnect_irq - disconnect irq service
+ * s3c_hsotg_disconnect - disconnect service
  * @hsotg: The device state.
  *
- * A disconnect IRQ has been received, meaning that the host has
- * lost contact with the bus. Remove all current transactions
- * and signal the gadget driver that this has happened.
-*/
-static void s3c_hsotg_disconnect_irq(struct s3c_hsotg *hsotg)
+ * The device has been disconnected. Remove all current
+ * transactions and signal the gadget driver that this
+ * has happened.
+ */
+static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg)
 {
 	unsigned ep;
 
-	for (ep = 0; ep < S3C_HSOTG_EPS; ep++)
+	for (ep = 0; ep < hsotg->num_of_eps; ep++)
 		kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true);
 
 	call_gadget(hsotg, disconnect);
@@ -2062,7 +2178,7 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
 
 	/* look through for any more data to transmit */
 
-	for (epno = 0; epno < S3C_HSOTG_EPS; epno++) {
+	for (epno = 0; epno < hsotg->num_of_eps; epno++) {
 		ep = &hsotg->eps[epno];
 
 		if (!ep->dir_in)
@@ -2078,12 +2194,187 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
 	}
 }
 
-static struct s3c_hsotg *our_hsotg;
-
 /* IRQ flags which will trigger a retry around the IRQ loop */
-#define IRQ_RETRY_MASK (S3C_GINTSTS_NPTxFEmp | \
-			S3C_GINTSTS_PTxFEmp |  \
-			S3C_GINTSTS_RxFLvl)
+#define IRQ_RETRY_MASK (GINTSTS_NPTxFEmp | \
+			GINTSTS_PTxFEmp |  \
+			GINTSTS_RxFLvl)
+
+/**
+ * s3c_hsotg_corereset - issue softreset to the core
+ * @hsotg: The device state
+ *
+ * Issue a soft reset to the core, and await the core finishing it.
+ */
+static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
+{
+	int timeout;
+	u32 grstctl;
+
+	dev_dbg(hsotg->dev, "resetting core\n");
+
+	/* issue soft reset */
+	writel(GRSTCTL_CSftRst, hsotg->regs + GRSTCTL);
+
+	timeout = 1000;
+	do {
+		grstctl = readl(hsotg->regs + GRSTCTL);
+	} while ((grstctl & GRSTCTL_CSftRst) && timeout-- > 0);
+
+	if (grstctl & GRSTCTL_CSftRst) {
+		dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
+		return -EINVAL;
+	}
+
+	timeout = 1000;
+
+	while (1) {
+		u32 grstctl = readl(hsotg->regs + GRSTCTL);
+
+		if (timeout-- < 0) {
+			dev_info(hsotg->dev,
+				 "%s: reset failed, GRSTCTL=%08x\n",
+				 __func__, grstctl);
+			return -ETIMEDOUT;
+		}
+
+		if (!(grstctl & GRSTCTL_AHBIdle))
+			continue;
+
+		break;		/* reset done */
+	}
+
+	dev_dbg(hsotg->dev, "reset successful\n");
+	return 0;
+}
+
+/**
+ * s3c_hsotg_core_init - issue softreset to the core
+ * @hsotg: The device state
+ *
+ * Issue a soft reset to the core, and await the core finishing it.
+ */
+static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
+{
+	s3c_hsotg_corereset(hsotg);
+
+	/*
+	 * we must now enable ep0 ready for host detection and then
+	 * set configuration.
+	 */
+
+	/* set the PLL on, remove the HNP/SRP and set the PHY */
+	writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) |
+	       (0x5 << 10), hsotg->regs + GUSBCFG);
+
+	s3c_hsotg_init_fifo(hsotg);
+
+	__orr32(hsotg->regs + DCTL, DCTL_SftDiscon);
+
+	writel(1 << 18 | DCFG_DevSpd_HS,  hsotg->regs + DCFG);
+
+	/* Clear any pending OTG interrupts */
+	writel(0xffffffff, hsotg->regs + GOTGINT);
+
+	/* Clear any pending interrupts */
+	writel(0xffffffff, hsotg->regs + GINTSTS);
+
+	writel(GINTSTS_ErlySusp | GINTSTS_SessReqInt |
+	       GINTSTS_GOUTNakEff | GINTSTS_GINNakEff |
+	       GINTSTS_ConIDStsChng | GINTSTS_USBRst |
+	       GINTSTS_EnumDone | GINTSTS_OTGInt |
+	       GINTSTS_USBSusp | GINTSTS_WkUpInt,
+	       hsotg->regs + GINTMSK);
+
+	if (using_dma(hsotg))
+		writel(GAHBCFG_GlblIntrEn | GAHBCFG_DMAEn |
+		       GAHBCFG_HBstLen_Incr4,
+		       hsotg->regs + GAHBCFG);
+	else
+		writel(GAHBCFG_GlblIntrEn, hsotg->regs + GAHBCFG);
+
+	/*
+	 * Enabling INTknTXFEmpMsk here seems to be a big mistake, we end
+	 * up being flooded with interrupts if the host is polling the
+	 * endpoint to try and read data.
+	 */
+
+	writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty : 0) |
+	       DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk |
+	       DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk |
+	       DIEPMSK_INTknEPMisMsk,
+	       hsotg->regs + DIEPMSK);
+
+	/*
+	 * don't need XferCompl, we get that from RXFIFO in slave mode. In
+	 * DMA mode we may need this.
+	 */
+	writel((using_dma(hsotg) ? (DIEPMSK_XferComplMsk |
+				    DIEPMSK_TimeOUTMsk) : 0) |
+	       DOEPMSK_EPDisbldMsk | DOEPMSK_AHBErrMsk |
+	       DOEPMSK_SetupMsk,
+	       hsotg->regs + DOEPMSK);
+
+	writel(0, hsotg->regs + DAINTMSK);
+
+	dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+		readl(hsotg->regs + DIEPCTL0),
+		readl(hsotg->regs + DOEPCTL0));
+
+	/* enable in and out endpoint interrupts */
+	s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPInt | GINTSTS_IEPInt);
+
+	/*
+	 * Enable the RXFIFO when in slave mode, as this is how we collect
+	 * the data. In DMA mode, we get events from the FIFO but also
+	 * things we cannot process, so do not use it.
+	 */
+	if (!using_dma(hsotg))
+		s3c_hsotg_en_gsint(hsotg, GINTSTS_RxFLvl);
+
+	/* Enable interrupts for EP0 in and out */
+	s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
+	s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);
+
+	__orr32(hsotg->regs + DCTL, DCTL_PWROnPrgDone);
+	udelay(10);  /* see openiboot */
+	__bic32(hsotg->regs + DCTL, DCTL_PWROnPrgDone);
+
+	dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL));
+
+	/*
+	 * DxEPCTL_USBActEp says RO in manual, but seems to be set by
+	 * writing to the EPCTL register..
+	 */
+
+	/* set to read 1 8byte packet */
+	writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) |
+	       DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0);
+
+	writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
+	       DxEPCTL_CNAK | DxEPCTL_EPEna |
+	       DxEPCTL_USBActEp,
+	       hsotg->regs + DOEPCTL0);
+
+	/* enable, but don't activate EP0in */
+	writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
+	       DxEPCTL_USBActEp, hsotg->regs + DIEPCTL0);
+
+	s3c_hsotg_enqueue_setup(hsotg);
+
+	dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+		readl(hsotg->regs + DIEPCTL0),
+		readl(hsotg->regs + DOEPCTL0));
+
+	/* clear global NAKs */
+	writel(DCTL_CGOUTNak | DCTL_CGNPInNAK,
+	       hsotg->regs + DCTL);
+
+	/* must be at-least 3ms to allow bus to see disconnect */
+	mdelay(3);
+
+	/* remove the soft-disconnect and let's go */
+	__bic32(hsotg->regs + DCTL, DCTL_SftDiscon);
+}
 
 /**
  * s3c_hsotg_irq - handle device interrupt
@@ -2098,52 +2389,45 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
 	u32 gintmsk;
 
 irq_retry:
-	gintsts = readl(hsotg->regs + S3C_GINTSTS);
-	gintmsk = readl(hsotg->regs + S3C_GINTMSK);
+	gintsts = readl(hsotg->regs + GINTSTS);
+	gintmsk = readl(hsotg->regs + GINTMSK);
 
 	dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n",
 		__func__, gintsts, gintsts & gintmsk, gintmsk, retry_count);
 
 	gintsts &= gintmsk;
 
-	if (gintsts & S3C_GINTSTS_OTGInt) {
-		u32 otgint = readl(hsotg->regs + S3C_GOTGINT);
+	if (gintsts & GINTSTS_OTGInt) {
+		u32 otgint = readl(hsotg->regs + GOTGINT);
 
 		dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
 
-		writel(otgint, hsotg->regs + S3C_GOTGINT);
+		writel(otgint, hsotg->regs + GOTGINT);
 	}
 
-	if (gintsts & S3C_GINTSTS_DisconnInt) {
-		dev_dbg(hsotg->dev, "%s: DisconnInt\n", __func__);
-		writel(S3C_GINTSTS_DisconnInt, hsotg->regs + S3C_GINTSTS);
-
-		s3c_hsotg_disconnect_irq(hsotg);
-	}
-
-	if (gintsts & S3C_GINTSTS_SessReqInt) {
+	if (gintsts & GINTSTS_SessReqInt) {
 		dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__);
-		writel(S3C_GINTSTS_SessReqInt, hsotg->regs + S3C_GINTSTS);
+		writel(GINTSTS_SessReqInt, hsotg->regs + GINTSTS);
 	}
 
-	if (gintsts & S3C_GINTSTS_EnumDone) {
-		writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS);
+	if (gintsts & GINTSTS_EnumDone) {
+		writel(GINTSTS_EnumDone, hsotg->regs + GINTSTS);
 
 		s3c_hsotg_irq_enumdone(hsotg);
 	}
 
-	if (gintsts & S3C_GINTSTS_ConIDStsChng) {
+	if (gintsts & GINTSTS_ConIDStsChng) {
 		dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n",
-			readl(hsotg->regs + S3C_DSTS),
-			readl(hsotg->regs + S3C_GOTGCTL));
+			readl(hsotg->regs + DSTS),
+			readl(hsotg->regs + GOTGCTL));
 
-		writel(S3C_GINTSTS_ConIDStsChng, hsotg->regs + S3C_GINTSTS);
+		writel(GINTSTS_ConIDStsChng, hsotg->regs + GINTSTS);
 	}
 
-	if (gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt)) {
-		u32 daint = readl(hsotg->regs + S3C_DAINT);
-		u32 daint_out = daint >> S3C_DAINT_OutEP_SHIFT;
-		u32 daint_in = daint & ~(daint_out << S3C_DAINT_OutEP_SHIFT);
+	if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) {
+		u32 daint = readl(hsotg->regs + DAINT);
+		u32 daint_out = daint >> DAINT_OutEP_SHIFT;
+		u32 daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT);
 		int ep;
 
 		dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
@@ -2159,102 +2443,116 @@ irq_retry:
 		}
 	}
 
-	if (gintsts & S3C_GINTSTS_USBRst) {
+	if (gintsts & GINTSTS_USBRst) {
+
+		u32 usb_status = readl(hsotg->regs + GOTGCTL);
+
 		dev_info(hsotg->dev, "%s: USBRst\n", __func__);
 		dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
-			readl(hsotg->regs + S3C_GNPTXSTS));
+			readl(hsotg->regs + GNPTXSTS));
 
-		writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
+		writel(GINTSTS_USBRst, hsotg->regs + GINTSTS);
 
-		kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
+		if (usb_status & GOTGCTL_BSESVLD) {
+			if (time_after(jiffies, hsotg->last_rst +
+				       msecs_to_jiffies(200))) {
 
-		/* it seems after a reset we can end up with a situation
-		 * where the TXFIFO still has data in it... the docs
-		 * suggest resetting all the fifos, so use the init_fifo
-		 * code to relayout and flush the fifos.
-		 */
+				kill_all_requests(hsotg, &hsotg->eps[0],
+							  -ECONNRESET, true);
 
-		s3c_hsotg_init_fifo(hsotg);
-
-		s3c_hsotg_enqueue_setup(hsotg);
+				s3c_hsotg_core_init(hsotg);
+				hsotg->last_rst = jiffies;
+			}
+		}
 	}
 
 	/* check both FIFOs */
 
-	if (gintsts & S3C_GINTSTS_NPTxFEmp) {
+	if (gintsts & GINTSTS_NPTxFEmp) {
 		dev_dbg(hsotg->dev, "NPTxFEmp\n");
 
-		/* Disable the interrupt to stop it happening again
+		/*
+		 * Disable the interrupt to stop it happening again
 		 * unless one of these endpoint routines decides that
-		 * it needs re-enabling */
+		 * it needs re-enabling
+		 */
 
-		s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp);
+		s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTxFEmp);
 		s3c_hsotg_irq_fifoempty(hsotg, false);
 	}
 
-	if (gintsts & S3C_GINTSTS_PTxFEmp) {
+	if (gintsts & GINTSTS_PTxFEmp) {
 		dev_dbg(hsotg->dev, "PTxFEmp\n");
 
-		/* See note in S3C_GINTSTS_NPTxFEmp */
+		/* See note in GINTSTS_NPTxFEmp */
 
-		s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+		s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTxFEmp);
 		s3c_hsotg_irq_fifoempty(hsotg, true);
 	}
 
-	if (gintsts & S3C_GINTSTS_RxFLvl) {
-		/* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
+	if (gintsts & GINTSTS_RxFLvl) {
+		/*
+		 * note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
 		 * we need to retry s3c_hsotg_handle_rx if this is still
-		 * set. */
+		 * set.
+		 */
 
 		s3c_hsotg_handle_rx(hsotg);
 	}
 
-	if (gintsts & S3C_GINTSTS_ModeMis) {
+	if (gintsts & GINTSTS_ModeMis) {
 		dev_warn(hsotg->dev, "warning, mode mismatch triggered\n");
-		writel(S3C_GINTSTS_ModeMis, hsotg->regs + S3C_GINTSTS);
+		writel(GINTSTS_ModeMis, hsotg->regs + GINTSTS);
 	}
 
-	if (gintsts & S3C_GINTSTS_USBSusp) {
-		dev_info(hsotg->dev, "S3C_GINTSTS_USBSusp\n");
-		writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS);
+	if (gintsts & GINTSTS_USBSusp) {
+		dev_info(hsotg->dev, "GINTSTS_USBSusp\n");
+		writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS);
 
 		call_gadget(hsotg, suspend);
+		s3c_hsotg_disconnect(hsotg);
 	}
 
-	if (gintsts & S3C_GINTSTS_WkUpInt) {
-		dev_info(hsotg->dev, "S3C_GINTSTS_WkUpIn\n");
-		writel(S3C_GINTSTS_WkUpInt, hsotg->regs + S3C_GINTSTS);
+	if (gintsts & GINTSTS_WkUpInt) {
+		dev_info(hsotg->dev, "GINTSTS_WkUpIn\n");
+		writel(GINTSTS_WkUpInt, hsotg->regs + GINTSTS);
 
 		call_gadget(hsotg, resume);
 	}
 
-	if (gintsts & S3C_GINTSTS_ErlySusp) {
-		dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n");
-		writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS);
+	if (gintsts & GINTSTS_ErlySusp) {
+		dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
+		writel(GINTSTS_ErlySusp, hsotg->regs + GINTSTS);
+
+		s3c_hsotg_disconnect(hsotg);
 	}
 
-	/* these next two seem to crop-up occasionally causing the core
+	/*
+	 * these next two seem to crop-up occasionally causing the core
 	 * to shutdown the USB transfer, so try clearing them and logging
-	 * the occurrence. */
+	 * the occurrence.
+	 */
 
-	if (gintsts & S3C_GINTSTS_GOUTNakEff) {
+	if (gintsts & GINTSTS_GOUTNakEff) {
 		dev_info(hsotg->dev, "GOUTNakEff triggered\n");
 
-		writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL);
+		writel(DCTL_CGOUTNak, hsotg->regs + DCTL);
 
 		s3c_hsotg_dump(hsotg);
 	}
 
-	if (gintsts & S3C_GINTSTS_GINNakEff) {
+	if (gintsts & GINTSTS_GINNakEff) {
 		dev_info(hsotg->dev, "GINNakEff triggered\n");
 
-		writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL);
+		writel(DCTL_CGNPInNAK, hsotg->regs + DCTL);
 
 		s3c_hsotg_dump(hsotg);
 	}
 
-	/* if we've had fifo events, we should try and go around the
-	 * loop again to see if there's any point in returning yet. */
+	/*
+	 * if we've had fifo events, we should try and go around the
+	 * loop again to see if there's any point in returning yet.
+	 */
 
 	if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
 			goto irq_retry;
@@ -2268,7 +2566,7 @@ irq_retry:
  * @desc: The USB endpoint descriptor to configure with.
  *
  * This is called from the USB gadget code's usb_ep_enable().
-*/
+ */
 static int s3c_hsotg_ep_enable(struct usb_ep *ep,
 			       const struct usb_endpoint_descriptor *desc)
 {
@@ -2300,7 +2598,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
 
 	/* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */
 
-	epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index);
+	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 	epctrl = readl(hsotg->regs + epctrl_reg);
 
 	dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
@@ -2308,20 +2606,23 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
 
 	spin_lock_irqsave(&hs_ep->lock, flags);
 
-	epctrl &= ~(S3C_DxEPCTL_EPType_MASK | S3C_DxEPCTL_MPS_MASK);
-	epctrl |= S3C_DxEPCTL_MPS(mps);
+	epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK);
+	epctrl |= DxEPCTL_MPS(mps);
 
-	/* mark the endpoint as active, otherwise the core may ignore
-	 * transactions entirely for this endpoint */
-	epctrl |= S3C_DxEPCTL_USBActEp;
+	/*
+	 * mark the endpoint as active, otherwise the core may ignore
+	 * transactions entirely for this endpoint
+	 */
+	epctrl |= DxEPCTL_USBActEp;
 
-	/* set the NAK status on the endpoint, otherwise we might try and
+	/*
+	 * set the NAK status on the endpoint, otherwise we might try and
 	 * do something with data that we've yet got a request to process
 	 * since the RXFIFO will take data for an endpoint even if the
 	 * size register hasn't been set.
 	 */
 
-	epctrl |= S3C_DxEPCTL_SNAK;
+	epctrl |= DxEPCTL_SNAK;
 
 	/* update the endpoint state */
 	hs_ep->ep.maxpacket = mps;
@@ -2336,37 +2637,40 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
 		goto out;
 
 	case USB_ENDPOINT_XFER_BULK:
-		epctrl |= S3C_DxEPCTL_EPType_Bulk;
+		epctrl |= DxEPCTL_EPType_Bulk;
 		break;
 
 	case USB_ENDPOINT_XFER_INT:
 		if (dir_in) {
-			/* Allocate our TxFNum by simply using the index
+			/*
+			 * Allocate our TxFNum by simply using the index
 			 * of the endpoint for the moment. We could do
 			 * something better if the host indicates how
-			 * many FIFOs we are expecting to use. */
+			 * many FIFOs we are expecting to use.
+			 */
 
 			hs_ep->periodic = 1;
-			epctrl |= S3C_DxEPCTL_TxFNum(index);
+			epctrl |= DxEPCTL_TxFNum(index);
 		}
 
-		epctrl |= S3C_DxEPCTL_EPType_Intterupt;
+		epctrl |= DxEPCTL_EPType_Intterupt;
 		break;
 
 	case USB_ENDPOINT_XFER_CONTROL:
-		epctrl |= S3C_DxEPCTL_EPType_Control;
+		epctrl |= DxEPCTL_EPType_Control;
 		break;
 	}
 
-	/* if the hardware has dedicated fifos, we must give each IN EP
+	/*
+	 * if the hardware has dedicated fifos, we must give each IN EP
 	 * a unique tx-fifo even if it is non-periodic.
 	 */
 	if (dir_in && hsotg->dedicated_fifos)
-		epctrl |= S3C_DxEPCTL_TxFNum(index);
+		epctrl |= DxEPCTL_TxFNum(index);
 
 	/* for non control endpoints, set PID to D0 */
 	if (index)
-		epctrl |= S3C_DxEPCTL_SetD0PID;
+		epctrl |= DxEPCTL_SetD0PID;
 
 	dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
 		__func__, epctrl);
@@ -2383,6 +2687,10 @@ out:
 	return ret;
 }
 
+/**
+ * s3c_hsotg_ep_disable - disable given endpoint
+ * @ep: The endpoint to disable.
+ */
 static int s3c_hsotg_ep_disable(struct usb_ep *ep)
 {
 	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
@@ -2400,7 +2708,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
 		return -EINVAL;
 	}
 
-	epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index);
+	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 
 	/* terminate all requests with shutdown */
 	kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
@@ -2408,9 +2716,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
 	spin_lock_irqsave(&hs_ep->lock, flags);
 
 	ctrl = readl(hsotg->regs + epctrl_reg);
-	ctrl &= ~S3C_DxEPCTL_EPEna;
-	ctrl &= ~S3C_DxEPCTL_USBActEp;
-	ctrl |= S3C_DxEPCTL_SNAK;
+	ctrl &= ~DxEPCTL_EPEna;
+	ctrl &= ~DxEPCTL_USBActEp;
+	ctrl |= DxEPCTL_SNAK;
 
 	dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
 	writel(ctrl, hsotg->regs + epctrl_reg);
@@ -2426,7 +2734,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
  * on_list - check request is on the given endpoint
  * @ep: The endpoint to check.
  * @test: The request to test if it is on the endpoint.
-*/
+ */
 static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
 {
 	struct s3c_hsotg_req *req, *treq;
@@ -2439,6 +2747,11 @@ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
 	return false;
 }
 
+/**
+ * s3c_hsotg_ep_dequeue - dequeue given endpoint
+ * @ep: The endpoint to dequeue.
+ * @req: The request to be removed from a queue.
+ */
 static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 {
 	struct s3c_hsotg_req *hs_req = our_req(req);
@@ -2461,6 +2774,11 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 	return 0;
 }
 
+/**
+ * s3c_hsotg_ep_sethalt - set halt on a given endpoint
+ * @ep: The endpoint to set halt.
+ * @value: Set or unset the halt.
+ */
 static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 {
 	struct s3c_hsotg_ep *hs_ep = our_ep(ep);
@@ -2477,34 +2795,34 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 
 	/* write both IN and OUT control registers */
 
-	epreg = S3C_DIEPCTL(index);
+	epreg = DIEPCTL(index);
 	epctl = readl(hs->regs + epreg);
 
 	if (value) {
-		epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK;
-		if (epctl & S3C_DxEPCTL_EPEna)
-			epctl |= S3C_DxEPCTL_EPDis;
+		epctl |= DxEPCTL_Stall + DxEPCTL_SNAK;
+		if (epctl & DxEPCTL_EPEna)
+			epctl |= DxEPCTL_EPDis;
 	} else {
-		epctl &= ~S3C_DxEPCTL_Stall;
-		xfertype = epctl & S3C_DxEPCTL_EPType_MASK;
-		if (xfertype == S3C_DxEPCTL_EPType_Bulk ||
-			xfertype == S3C_DxEPCTL_EPType_Intterupt)
-				epctl |= S3C_DxEPCTL_SetD0PID;
+		epctl &= ~DxEPCTL_Stall;
+		xfertype = epctl & DxEPCTL_EPType_MASK;
+		if (xfertype == DxEPCTL_EPType_Bulk ||
+			xfertype == DxEPCTL_EPType_Intterupt)
+				epctl |= DxEPCTL_SetD0PID;
 	}
 
 	writel(epctl, hs->regs + epreg);
 
-	epreg = S3C_DOEPCTL(index);
+	epreg = DOEPCTL(index);
 	epctl = readl(hs->regs + epreg);
 
 	if (value)
-		epctl |= S3C_DxEPCTL_Stall;
+		epctl |= DxEPCTL_Stall;
 	else {
-		epctl &= ~S3C_DxEPCTL_Stall;
-		xfertype = epctl & S3C_DxEPCTL_EPType_MASK;
-		if (xfertype == S3C_DxEPCTL_EPType_Bulk ||
-			xfertype == S3C_DxEPCTL_EPType_Intterupt)
-				epctl |= S3C_DxEPCTL_SetD0PID;
+		epctl &= ~DxEPCTL_Stall;
+		xfertype = epctl & DxEPCTL_EPType_MASK;
+		if (xfertype == DxEPCTL_EPType_Bulk ||
+			xfertype == DxEPCTL_EPType_Intterupt)
+				epctl |= DxEPCTL_SetD0PID;
 	}
 
 	writel(epctl, hs->regs + epreg);
@@ -2526,57 +2844,91 @@ static struct usb_ep_ops s3c_hsotg_ep_ops = {
 };
 
 /**
- * s3c_hsotg_corereset - issue softreset to the core
- * @hsotg: The device state
+ * s3c_hsotg_phy_enable - enable platform phy dev
+ * @hsotg: The driver state
  *
- * Issue a soft reset to the core, and await the core finishing it.
-*/
-static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
+ * A wrapper for platform code responsible for controlling
+ * low-level USB code
+ */
+static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
 {
-	int timeout;
-	u32 grstctl;
+	struct platform_device *pdev = to_platform_device(hsotg->dev);
 
-	dev_dbg(hsotg->dev, "resetting core\n");
-
-	/* issue soft reset */
-	writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL);
-
-	timeout = 1000;
-	do {
-		grstctl = readl(hsotg->regs + S3C_GRSTCTL);
-	} while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0);
-
-	if (grstctl & S3C_GRSTCTL_CSftRst) {
-		dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
-		return -EINVAL;
-	}
-
-	timeout = 1000;
-
-	while (1) {
-		u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL);
-
-		if (timeout-- < 0) {
-			dev_info(hsotg->dev,
-				 "%s: reset failed, GRSTCTL=%08x\n",
-				 __func__, grstctl);
-			return -ETIMEDOUT;
-		}
-
-		if (!(grstctl & S3C_GRSTCTL_AHBIdle))
-			continue;
-
-		break;		/* reset done */
-	}
-
-	dev_dbg(hsotg->dev, "reset successful\n");
-	return 0;
+	dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
+	if (hsotg->plat->phy_init)
+		hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
 }
 
-static int s3c_hsotg_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
+/**
+ * s3c_hsotg_phy_disable - disable platform phy dev
+ * @hsotg: The driver state
+ *
+ * A wrapper for platform code responsible for controlling
+ * low-level USB code
+ */
+static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
 {
-	struct s3c_hsotg *hsotg = our_hsotg;
+	struct platform_device *pdev = to_platform_device(hsotg->dev);
+
+	if (hsotg->plat->phy_exit)
+		hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
+}
+
+/**
+ * s3c_hsotg_init - initalize the usb core
+ * @hsotg: The driver state
+ */
+static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
+{
+	/* unmask subset of endpoint interrupts */
+
+	writel(DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk |
+	       DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk,
+	       hsotg->regs + DIEPMSK);
+
+	writel(DOEPMSK_SetupMsk | DOEPMSK_AHBErrMsk |
+	       DOEPMSK_EPDisbldMsk | DOEPMSK_XferComplMsk,
+	       hsotg->regs + DOEPMSK);
+
+	writel(0, hsotg->regs + DAINTMSK);
+
+	/* Be in disconnected state until gadget is registered */
+	__orr32(hsotg->regs + DCTL, DCTL_SftDiscon);
+
+	if (0) {
+		/* post global nak until we're ready */
+		writel(DCTL_SGNPInNAK | DCTL_SGOUTNak,
+		       hsotg->regs + DCTL);
+	}
+
+	/* setup fifos */
+
+	dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
+		readl(hsotg->regs + GRXFSIZ),
+		readl(hsotg->regs + GNPTXFSIZ));
+
+	s3c_hsotg_init_fifo(hsotg);
+
+	/* set the PLL on, remove the HNP/SRP and set the PHY */
+	writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) | (0x5 << 10),
+	       hsotg->regs + GUSBCFG);
+
+	writel(using_dma(hsotg) ? GAHBCFG_DMAEn : 0x0,
+	       hsotg->regs + GAHBCFG);
+}
+
+/**
+ * s3c_hsotg_udc_start - prepare the udc for work
+ * @gadget: The usb gadget state
+ * @driver: The usb gadget driver
+ *
+ * Perform initialization to prepare udc device and driver
+ * to work.
+ */
+static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
+			   struct usb_gadget_driver *driver)
+{
+	struct s3c_hsotg *hsotg = to_hsotg(gadget);
 	int ret;
 
 	if (!hsotg) {
@@ -2592,7 +2944,7 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,
 	if (driver->max_speed < USB_SPEED_FULL)
 		dev_err(hsotg->dev, "%s: bad speed\n", __func__);
 
-	if (!bind || !driver->setup) {
+	if (!driver->setup) {
 		dev_err(hsotg->dev, "%s: missing entry points\n", __func__);
 		return -EINVAL;
 	}
@@ -2605,135 +2957,17 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,
 	hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
-	ret = device_add(&hsotg->gadget.dev);
+	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
+				    hsotg->supplies);
 	if (ret) {
-		dev_err(hsotg->dev, "failed to register gadget device\n");
+		dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
 		goto err;
 	}
 
-	ret = bind(&hsotg->gadget);
-	if (ret) {
-		dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name);
-
-		hsotg->gadget.dev.driver = NULL;
-		hsotg->driver = NULL;
-		goto err;
-	}
-
-	/* we must now enable ep0 ready for host detection and then
-	 * set configuration. */
-
-	s3c_hsotg_corereset(hsotg);
-
-	/* set the PLL on, remove the HNP/SRP and set the PHY */
-	writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) |
-	       (0x5 << 10), hsotg->regs + S3C_GUSBCFG);
-
-	/* looks like soft-reset changes state of FIFOs */
-	s3c_hsotg_init_fifo(hsotg);
-
-	__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
-
-	writel(1 << 18 | S3C_DCFG_DevSpd_HS,  hsotg->regs + S3C_DCFG);
-
-	/* Clear any pending OTG interrupts */
-	writel(0xffffffff, hsotg->regs + S3C_GOTGINT);
-
-	/* Clear any pending interrupts */
-	writel(0xffffffff, hsotg->regs + S3C_GINTSTS);
-
-	writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt |
-	       S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst |
-	       S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt |
-	       S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt |
-	       S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff |
-	       S3C_GINTSTS_ErlySusp,
-	       hsotg->regs + S3C_GINTMSK);
-
-	if (using_dma(hsotg))
-		writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn |
-		       S3C_GAHBCFG_HBstLen_Incr4,
-		       hsotg->regs + S3C_GAHBCFG);
-	else
-		writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG);
-
-	/* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end
-	 * up being flooded with interrupts if the host is polling the
-	 * endpoint to try and read data. */
-
-	writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
-	       S3C_DIEPMSK_INTknEPMisMsk |
-	       S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk |
-	       ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0),
-	       hsotg->regs + S3C_DIEPMSK);
-
-	/* don't need XferCompl, we get that from RXFIFO in slave mode. In
-	 * DMA mode we may need this. */
-	writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk |
-	       S3C_DOEPMSK_EPDisbldMsk |
-	       (using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk |
-				   S3C_DIEPMSK_TimeOUTMsk) : 0),
-	       hsotg->regs + S3C_DOEPMSK);
-
-	writel(0, hsotg->regs + S3C_DAINTMSK);
-
-	dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-		readl(hsotg->regs + S3C_DIEPCTL0),
-		readl(hsotg->regs + S3C_DOEPCTL0));
-
-	/* enable in and out endpoint interrupts */
-	s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt);
-
-	/* Enable the RXFIFO when in slave mode, as this is how we collect
-	 * the data. In DMA mode, we get events from the FIFO but also
-	 * things we cannot process, so do not use it. */
-	if (!using_dma(hsotg))
-		s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl);
-
-	/* Enable interrupts for EP0 in and out */
-	s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
-	s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);
-
-	__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
-	udelay(10);  /* see openiboot */
-	__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
-
-	dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL));
-
-	/* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by
-	   writing to the EPCTL register.. */
-
-	/* set to read 1 8byte packet */
-	writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |
-	       S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0);
-
-	writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
-	       S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna |
-	       S3C_DxEPCTL_USBActEp,
-	       hsotg->regs + S3C_DOEPCTL0);
-
-	/* enable, but don't activate EP0in */
-	writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
-	       S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0);
-
-	s3c_hsotg_enqueue_setup(hsotg);
-
-	dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-		readl(hsotg->regs + S3C_DIEPCTL0),
-		readl(hsotg->regs + S3C_DOEPCTL0));
-
-	/* clear global NAKs */
-	writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
-	       hsotg->regs + S3C_DCTL);
-
-	/* must be at-least 3ms to allow bus to see disconnect */
-	msleep(3);
-
-	/* remove the soft-disconnect and let's go */
-	__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
-
-	/* report to the user, and return */
+	s3c_hsotg_phy_enable(hsotg);
 
+	s3c_hsotg_core_init(hsotg);
+	hsotg->last_rst = jiffies;
 	dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
 	return 0;
 
@@ -2743,9 +2977,17 @@ err:
 	return ret;
 }
 
-static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
+/**
+ * s3c_hsotg_udc_stop - stop the udc
+ * @gadget: The usb gadget state
+ * @driver: The usb gadget driver
+ *
+ * Stop udc hw block and stay tunned for future transmissions
+ */
+static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
+			  struct usb_gadget_driver *driver)
 {
-	struct s3c_hsotg *hsotg = our_hsotg;
+	struct s3c_hsotg *hsotg = to_hsotg(gadget);
 	int ep;
 
 	if (!hsotg)
@@ -2755,16 +2997,15 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
 		return -EINVAL;
 
 	/* all endpoints should be shutdown */
-	for (ep = 0; ep < S3C_HSOTG_EPS; ep++)
+	for (ep = 0; ep < hsotg->num_of_eps; ep++)
 		s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
 
-	call_gadget(hsotg, disconnect);
+	s3c_hsotg_phy_disable(hsotg);
+	regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
-	driver->unbind(&hsotg->gadget);
 	hsotg->driver = NULL;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
-
-	device_del(&hsotg->gadget.dev);
+	hsotg->gadget.dev.driver = NULL;
 
 	dev_info(hsotg->dev, "unregistered gadget driver '%s'\n",
 		 driver->driver.name);
@@ -2772,6 +3013,12 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
 	return 0;
 }
 
+/**
+ * s3c_hsotg_gadget_getframe - read the frame number
+ * @gadget: The usb gadget state
+ *
+ * Read the {micro} frame number
+ */
 static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
 {
 	return s3c_hsotg_read_frameno(to_hsotg(gadget));
@@ -2779,8 +3026,8 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
 
 static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
 	.get_frame	= s3c_hsotg_gadget_getframe,
-	.start		= s3c_hsotg_start,
-	.stop		= s3c_hsotg_stop,
+	.udc_start		= s3c_hsotg_udc_start,
+	.udc_stop		= s3c_hsotg_udc_stop,
 };
 
 /**
@@ -2827,112 +3074,43 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
 	hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT;
 	hs_ep->ep.ops = &s3c_hsotg_ep_ops;
 
-	/* Read the FIFO size for the Periodic TX FIFO, even if we're
+	/*
+	 * Read the FIFO size for the Periodic TX FIFO, even if we're
 	 * an OUT endpoint, we may as well do this if in future the
 	 * code is changed to make each endpoint's direction changeable.
 	 */
 
-	ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum));
-	hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
+	ptxfifo = readl(hsotg->regs + DPTXFSIZn(epnum));
+	hs_ep->fifo_size = DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
 
-	/* if we're using dma, we need to set the next-endpoint pointer
+	/*
+	 * if we're using dma, we need to set the next-endpoint pointer
 	 * to be something valid.
 	 */
 
 	if (using_dma(hsotg)) {
-		u32 next = S3C_DxEPCTL_NextEp((epnum + 1) % 15);
-		writel(next, hsotg->regs + S3C_DIEPCTL(epnum));
-		writel(next, hsotg->regs + S3C_DOEPCTL(epnum));
+		u32 next = DxEPCTL_NextEp((epnum + 1) % 15);
+		writel(next, hsotg->regs + DIEPCTL(epnum));
+		writel(next, hsotg->regs + DOEPCTL(epnum));
 	}
 }
 
 /**
- * s3c_hsotg_otgreset - reset the OtG phy block
- * @hsotg: The host state.
+ * s3c_hsotg_hw_cfg - read HW configuration registers
+ * @param: The device state
  *
- * Power up the phy, set the basic configuration and start the PHY.
+ * Read the USB core HW configuration registers
  */
-static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_hw_cfg(struct s3c_hsotg *hsotg)
 {
-	struct clk *xusbxti;
-	u32 pwr, osc;
-
-	pwr = readl(S3C_PHYPWR);
-	pwr &= ~0x19;
-	writel(pwr, S3C_PHYPWR);
-	mdelay(1);
-
-	osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0;
-
-	xusbxti = clk_get(hsotg->dev, "xusbxti");
-	if (xusbxti && !IS_ERR(xusbxti)) {
-		switch (clk_get_rate(xusbxti)) {
-		case 12*MHZ:
-			osc |= S3C_PHYCLK_CLKSEL_12M;
-			break;
-		case 24*MHZ:
-			osc |= S3C_PHYCLK_CLKSEL_24M;
-			break;
-		default:
-		case 48*MHZ:
-			/* default reference clock */
-			break;
-		}
-		clk_put(xusbxti);
-	}
-
-	writel(osc | 0x10, S3C_PHYCLK);
-
-	/* issue a full set of resets to the otg and core */
-
-	writel(S3C_RSTCON_PHY, S3C_RSTCON);
-	udelay(20);	/* at-least 10uS */
-	writel(0, S3C_RSTCON);
-}
-
-
-static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
-{
-	u32 cfg4;
-
-	/* unmask subset of endpoint interrupts */
-
-	writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
-	       S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk,
-	       hsotg->regs + S3C_DIEPMSK);
-
-	writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk |
-	       S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk,
-	       hsotg->regs + S3C_DOEPMSK);
-
-	writel(0, hsotg->regs + S3C_DAINTMSK);
-
-	/* Be in disconnected state until gadget is registered */
-	__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
-
-	if (0) {
-		/* post global nak until we're ready */
-		writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,
-		       hsotg->regs + S3C_DCTL);
-	}
-
-	/* setup fifos */
-
-	dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
-		readl(hsotg->regs + S3C_GRXFSIZ),
-		readl(hsotg->regs + S3C_GNPTXFSIZ));
-
-	s3c_hsotg_init_fifo(hsotg);
-
-	/* set the PLL on, remove the HNP/SRP and set the PHY */
-	writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10),
-	       hsotg->regs + S3C_GUSBCFG);
-
-	writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0,
-	       hsotg->regs + S3C_GAHBCFG);
-
+	u32 cfg2, cfg4;
 	/* check hardware configuration */
 
+	cfg2 = readl(hsotg->regs + 0x48);
+	hsotg->num_of_eps = (cfg2 >> 10) & 0xF;
+
+	dev_info(hsotg->dev, "EPs:%d\n", hsotg->num_of_eps);
+
 	cfg4 = readl(hsotg->regs + 0x50);
 	hsotg->dedicated_fifos = (cfg4 >> 25) & 1;
 
@@ -2940,6 +3118,10 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
 		 hsotg->dedicated_fifos ? "dedicated" : "shared");
 }
 
+/**
+ * s3c_hsotg_dump - dump state of the udc
+ * @param: The device state
+ */
 static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
 {
 #ifdef DEBUG
@@ -2949,46 +3131,45 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
 	int idx;
 
 	dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n",
-		 readl(regs + S3C_DCFG), readl(regs + S3C_DCTL),
-		 readl(regs + S3C_DIEPMSK));
+		 readl(regs + DCFG), readl(regs + DCTL),
+		 readl(regs + DIEPMSK));
 
 	dev_info(dev, "GAHBCFG=0x%08x, 0x44=0x%08x\n",
-		 readl(regs + S3C_GAHBCFG), readl(regs + 0x44));
+		 readl(regs + GAHBCFG), readl(regs + 0x44));
 
 	dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
-		 readl(regs + S3C_GRXFSIZ), readl(regs + S3C_GNPTXFSIZ));
+		 readl(regs + GRXFSIZ), readl(regs + GNPTXFSIZ));
 
 	/* show periodic fifo settings */
 
 	for (idx = 1; idx <= 15; idx++) {
-		val = readl(regs + S3C_DPTXFSIZn(idx));
+		val = readl(regs + DPTXFSIZn(idx));
 		dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx,
-			 val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT,
-			 val & S3C_DPTXFSIZn_DPTxFStAddr_MASK);
+			 val >> DPTXFSIZn_DPTxFSize_SHIFT,
+			 val & DPTXFSIZn_DPTxFStAddr_MASK);
 	}
 
 	for (idx = 0; idx < 15; idx++) {
 		dev_info(dev,
 			 "ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx,
-			 readl(regs + S3C_DIEPCTL(idx)),
-			 readl(regs + S3C_DIEPTSIZ(idx)),
-			 readl(regs + S3C_DIEPDMA(idx)));
+			 readl(regs + DIEPCTL(idx)),
+			 readl(regs + DIEPTSIZ(idx)),
+			 readl(regs + DIEPDMA(idx)));
 
-		val = readl(regs + S3C_DOEPCTL(idx));
+		val = readl(regs + DOEPCTL(idx));
 		dev_info(dev,
 			 "ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n",
-			 idx, readl(regs + S3C_DOEPCTL(idx)),
-			 readl(regs + S3C_DOEPTSIZ(idx)),
-			 readl(regs + S3C_DOEPDMA(idx)));
+			 idx, readl(regs + DOEPCTL(idx)),
+			 readl(regs + DOEPTSIZ(idx)),
+			 readl(regs + DOEPDMA(idx)));
 
 	}
 
 	dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n",
-		 readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE));
+		 readl(regs + DVBUSDIS), readl(regs + DVBUSPULSE));
 #endif
 }
 
-
 /**
  * state_show - debugfs: show overall driver and device state.
  * @seq: The seq file to write to.
@@ -3005,38 +3186,38 @@ static int state_show(struct seq_file *seq, void *v)
 	int idx;
 
 	seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
-		 readl(regs + S3C_DCFG),
-		 readl(regs + S3C_DCTL),
-		 readl(regs + S3C_DSTS));
+		 readl(regs + DCFG),
+		 readl(regs + DCTL),
+		 readl(regs + DSTS));
 
 	seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n",
-		   readl(regs + S3C_DIEPMSK), readl(regs + S3C_DOEPMSK));
+		   readl(regs + DIEPMSK), readl(regs + DOEPMSK));
 
 	seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n",
-		   readl(regs + S3C_GINTMSK),
-		   readl(regs + S3C_GINTSTS));
+		   readl(regs + GINTMSK),
+		   readl(regs + GINTSTS));
 
 	seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n",
-		   readl(regs + S3C_DAINTMSK),
-		   readl(regs + S3C_DAINT));
+		   readl(regs + DAINTMSK),
+		   readl(regs + DAINT));
 
 	seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n",
-		   readl(regs + S3C_GNPTXSTS),
-		   readl(regs + S3C_GRXSTSR));
+		   readl(regs + GNPTXSTS),
+		   readl(regs + GRXSTSR));
 
 	seq_printf(seq, "\nEndpoint status:\n");
 
 	for (idx = 0; idx < 15; idx++) {
 		u32 in, out;
 
-		in = readl(regs + S3C_DIEPCTL(idx));
-		out = readl(regs + S3C_DOEPCTL(idx));
+		in = readl(regs + DIEPCTL(idx));
+		out = readl(regs + DOEPCTL(idx));
 
 		seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x",
 			   idx, in, out);
 
-		in = readl(regs + S3C_DIEPTSIZ(idx));
-		out = readl(regs + S3C_DOEPTSIZ(idx));
+		in = readl(regs + DIEPTSIZ(idx));
+		out = readl(regs + DOEPTSIZ(idx));
 
 		seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
 			   in, out);
@@ -3067,7 +3248,7 @@ static const struct file_operations state_fops = {
  *
  * Show the FIFO information for the overall fifo and all the
  * periodic transmission FIFOs.
-*/
+ */
 static int fifo_show(struct seq_file *seq, void *v)
 {
 	struct s3c_hsotg *hsotg = seq->private;
@@ -3076,21 +3257,21 @@ static int fifo_show(struct seq_file *seq, void *v)
 	int idx;
 
 	seq_printf(seq, "Non-periodic FIFOs:\n");
-	seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + S3C_GRXFSIZ));
+	seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ));
 
-	val = readl(regs + S3C_GNPTXFSIZ);
+	val = readl(regs + GNPTXFSIZ);
 	seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
-		   val >> S3C_GNPTXFSIZ_NPTxFDep_SHIFT,
-		   val & S3C_GNPTXFSIZ_NPTxFStAddr_MASK);
+		   val >> GNPTXFSIZ_NPTxFDep_SHIFT,
+		   val & GNPTXFSIZ_NPTxFStAddr_MASK);
 
 	seq_printf(seq, "\nPeriodic TXFIFOs:\n");
 
 	for (idx = 1; idx <= 15; idx++) {
-		val = readl(regs + S3C_DPTXFSIZn(idx));
+		val = readl(regs + DPTXFSIZn(idx));
 
 		seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
-			   val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT,
-			   val & S3C_DPTXFSIZn_DPTxFStAddr_MASK);
+			   val >> DPTXFSIZn_DPTxFSize_SHIFT,
+			   val & DPTXFSIZn_DPTxFStAddr_MASK);
 	}
 
 	return 0;
@@ -3122,7 +3303,7 @@ static const char *decode_direction(int is_in)
  *
  * This debugfs entry shows the state of the given endpoint (one is
  * registered for each available).
-*/
+ */
 static int ep_show(struct seq_file *seq, void *v)
 {
 	struct s3c_hsotg_ep *ep = seq->private;
@@ -3139,20 +3320,20 @@ static int ep_show(struct seq_file *seq, void *v)
 	/* first show the register state */
 
 	seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n",
-		   readl(regs + S3C_DIEPCTL(index)),
-		   readl(regs + S3C_DOEPCTL(index)));
+		   readl(regs + DIEPCTL(index)),
+		   readl(regs + DOEPCTL(index)));
 
 	seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n",
-		   readl(regs + S3C_DIEPDMA(index)),
-		   readl(regs + S3C_DOEPDMA(index)));
+		   readl(regs + DIEPDMA(index)),
+		   readl(regs + DOEPDMA(index)));
 
 	seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n",
-		   readl(regs + S3C_DIEPINT(index)),
-		   readl(regs + S3C_DOEPINT(index)));
+		   readl(regs + DIEPINT(index)),
+		   readl(regs + DOEPINT(index)));
 
 	seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n",
-		   readl(regs + S3C_DIEPTSIZ(index)),
-		   readl(regs + S3C_DOEPTSIZ(index)));
+		   readl(regs + DIEPTSIZ(index)),
+		   readl(regs + DOEPTSIZ(index)));
 
 	seq_printf(seq, "\n");
 	seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
@@ -3202,7 +3383,7 @@ static const struct file_operations ep_fops = {
  * about the state of the system. The directory name is created
  * with the same name as the device itself, in case we end up
  * with multiple blocks in future systems.
-*/
+ */
 static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
 {
 	struct dentry *root;
@@ -3231,7 +3412,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
 
 	/* create one file for each endpoint */
 
-	for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) {
+	for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
 		struct s3c_hsotg_ep *ep = &hsotg->eps[epidx];
 
 		ep->debugfs = debugfs_create_file(ep->name, 0444,
@@ -3248,12 +3429,12 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
  * @hsotg: The driver state
  *
  * Cleanup (remove) the debugfs files for use on module exit.
-*/
+ */
 static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 {
 	unsigned epidx;
 
-	for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) {
+	for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
 		struct s3c_hsotg_ep *ep = &hsotg->eps[epidx];
 		debugfs_remove(ep->debugfs);
 	}
@@ -3264,48 +3445,39 @@ static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 }
 
 /**
- * s3c_hsotg_gate - set the hardware gate for the block
- * @pdev: The device we bound to
- * @on: On or off.
- *
- * Set the hardware gate setting into the block. If we end up on
- * something other than an S3C64XX, then we might need to change this
- * to using a platform data callback, or some other mechanism.
+ * s3c_hsotg_release - release callback for hsotg device
+ * @dev: Device to for which release is called
  */
-static void s3c_hsotg_gate(struct platform_device *pdev, bool on)
+static void s3c_hsotg_release(struct device *dev)
 {
-	unsigned long flags;
-	u32 others;
+	struct s3c_hsotg *hsotg = dev_get_drvdata(dev);
 
-	local_irq_save(flags);
-
-	others = __raw_readl(S3C64XX_OTHERS);
-	if (on)
-		others |= S3C64XX_OTHERS_USBMASK;
-	else
-		others &= ~S3C64XX_OTHERS_USBMASK;
-	__raw_writel(others, S3C64XX_OTHERS);
-
-	local_irq_restore(flags);
+	kfree(hsotg);
 }
 
-static struct s3c_hsotg_plat s3c_hsotg_default_pdata;
+/**
+ * s3c_hsotg_probe - probe function for hsotg driver
+ * @pdev: The platform information for the driver
+ */
 
 static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 {
 	struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
 	struct device *dev = &pdev->dev;
+	struct s3c_hsotg_ep *eps;
 	struct s3c_hsotg *hsotg;
 	struct resource *res;
 	int epnum;
 	int ret;
+	int i;
 
-	if (!plat)
-		plat = &s3c_hsotg_default_pdata;
+	plat = pdev->dev.platform_data;
+	if (!plat) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
 
-	hsotg = kzalloc(sizeof(struct s3c_hsotg) +
-			sizeof(struct s3c_hsotg_ep) * S3C_HSOTG_EPS,
-			GFP_KERNEL);
+	hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL);
 	if (!hsotg) {
 		dev_err(dev, "cannot get memory\n");
 		return -ENOMEM;
@@ -3371,6 +3543,54 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 
 	hsotg->gadget.dev.parent = dev;
 	hsotg->gadget.dev.dma_mask = dev->dma_mask;
+	hsotg->gadget.dev.release = s3c_hsotg_release;
+
+	/* reset the system */
+
+	clk_prepare_enable(hsotg->clk);
+
+	/* regulators */
+
+	for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
+		hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
+
+	ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
+				 hsotg->supplies);
+	if (ret) {
+		dev_err(dev, "failed to request supplies: %d\n", ret);
+		goto err_irq;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
+				    hsotg->supplies);
+
+	if (ret) {
+		dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
+		goto err_supplies;
+	}
+
+	/* usb phy enable */
+	s3c_hsotg_phy_enable(hsotg);
+
+	s3c_hsotg_corereset(hsotg);
+	s3c_hsotg_init(hsotg);
+	s3c_hsotg_hw_cfg(hsotg);
+
+	/* hsotg->num_of_eps holds number of EPs other than ep0 */
+
+	if (hsotg->num_of_eps == 0) {
+		dev_err(dev, "wrong number of EPs (zero)\n");
+		goto err_supplies;
+	}
+
+	eps = kcalloc(hsotg->num_of_eps + 1, sizeof(struct s3c_hsotg_ep),
+		      GFP_KERNEL);
+	if (!eps) {
+		dev_err(dev, "cannot get memory\n");
+		goto err_supplies;
+	}
+
+	hsotg->eps = eps;
 
 	/* setup endpoint information */
 
@@ -3383,39 +3603,47 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 						     GFP_KERNEL);
 	if (!hsotg->ctrl_req) {
 		dev_err(dev, "failed to allocate ctrl req\n");
-		goto err_regs;
+		goto err_ep_mem;
 	}
 
-	/* reset the system */
-
-	clk_enable(hsotg->clk);
-
-	s3c_hsotg_gate(pdev, true);
-
-	s3c_hsotg_otgreset(hsotg);
-	s3c_hsotg_corereset(hsotg);
-	s3c_hsotg_init(hsotg);
-
 	/* initialise the endpoints now the core has been initialised */
-	for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++)
+	for (epnum = 0; epnum < hsotg->num_of_eps; epnum++)
 		s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
 
+	/* disable power and clock */
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
+				    hsotg->supplies);
+	if (ret) {
+		dev_err(hsotg->dev, "failed to disable supplies: %d\n", ret);
+		goto err_ep_mem;
+	}
+
+	s3c_hsotg_phy_disable(hsotg);
+
+	ret = device_add(&hsotg->gadget.dev);
+	if (ret) {
+		put_device(&hsotg->gadget.dev);
+		goto err_ep_mem;
+	}
+
 	ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
 	if (ret)
-		goto err_add_udc;
+		goto err_ep_mem;
 
 	s3c_hsotg_create_debug(hsotg);
 
 	s3c_hsotg_dump(hsotg);
 
-	our_hsotg = hsotg;
 	return 0;
 
-err_add_udc:
-	s3c_hsotg_gate(pdev, false);
-	clk_disable(hsotg->clk);
-	clk_put(hsotg->clk);
-
+err_ep_mem:
+	kfree(eps);
+err_supplies:
+	s3c_hsotg_phy_disable(hsotg);
+	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
+err_irq:
+	free_irq(hsotg->irq, hsotg);
 err_regs:
 	iounmap(hsotg->regs);
 
@@ -3423,12 +3651,17 @@ err_regs_res:
 	release_resource(hsotg->regs_res);
 	kfree(hsotg->regs_res);
 err_clk:
+	clk_disable_unprepare(hsotg->clk);
 	clk_put(hsotg->clk);
 err_mem:
 	kfree(hsotg);
 	return ret;
 }
 
+/**
+ * s3c_hsotg_remove - remove function for hsotg driver
+ * @pdev: The platform information for the driver
+ */
 static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
 {
 	struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
@@ -3437,7 +3670,10 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
 
 	s3c_hsotg_delete_debug(hsotg);
 
-	usb_gadget_unregister_driver(hsotg->driver);
+	if (hsotg->driver) {
+		/* should have been done already by driver model core */
+		usb_gadget_unregister_driver(hsotg->driver);
+	}
 
 	free_irq(hsotg->irq, hsotg);
 	iounmap(hsotg->regs);
@@ -3445,12 +3681,13 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
 	release_resource(hsotg->regs_res);
 	kfree(hsotg->regs_res);
 
-	s3c_hsotg_gate(pdev, false);
+	s3c_hsotg_phy_disable(hsotg);
+	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
-	clk_disable(hsotg->clk);
+	clk_disable_unprepare(hsotg->clk);
 	clk_put(hsotg->clk);
 
-	kfree(hsotg);
+	device_unregister(&hsotg->gadget.dev);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/s3c-hsotg.h b/drivers/usb/gadget/s3c-hsotg.h
new file mode 100644
index 000000000000..d650b1295831
--- /dev/null
+++ b/drivers/usb/gadget/s3c-hsotg.h
@@ -0,0 +1,377 @@
+/* drivers/usb/gadget/s3c-hsotg.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * USB2.0 Highspeed/OtG Synopsis DWC2 device block registers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __REGS_USB_HSOTG_H
+#define __REGS_USB_HSOTG_H __FILE__
+
+#define HSOTG_REG(x) (x)
+
+#define GOTGCTL				HSOTG_REG(0x000)
+#define GOTGCTL_BSESVLD			(1 << 19)
+#define GOTGCTL_ASESVLD			(1 << 18)
+#define GOTGCTL_DBNC_SHORT			(1 << 17)
+#define GOTGCTL_CONID_B			(1 << 16)
+#define GOTGCTL_DEVHNPEN			(1 << 11)
+#define GOTGCTL_HSSETHNPEN			(1 << 10)
+#define GOTGCTL_HNPREQ				(1 << 9)
+#define GOTGCTL_HSTNEGSCS			(1 << 8)
+#define GOTGCTL_SESREQ				(1 << 1)
+#define GOTGCTL_SESREQSCS			(1 << 0)
+
+#define GOTGINT				HSOTG_REG(0x004)
+#define GOTGINT_DbnceDone			(1 << 19)
+#define GOTGINT_ADevTOUTChg			(1 << 18)
+#define GOTGINT_HstNegDet			(1 << 17)
+#define GOTGINT_HstnegSucStsChng		(1 << 9)
+#define GOTGINT_SesReqSucStsChng		(1 << 8)
+#define GOTGINT_SesEndDet			(1 << 2)
+
+#define GAHBCFG				HSOTG_REG(0x008)
+#define GAHBCFG_PTxFEmpLvl			(1 << 8)
+#define GAHBCFG_NPTxFEmpLvl			(1 << 7)
+#define GAHBCFG_DMAEn				(1 << 5)
+#define GAHBCFG_HBstLen_MASK			(0xf << 1)
+#define GAHBCFG_HBstLen_SHIFT			(1)
+#define GAHBCFG_HBstLen_Single			(0x0 << 1)
+#define GAHBCFG_HBstLen_Incr			(0x1 << 1)
+#define GAHBCFG_HBstLen_Incr4			(0x3 << 1)
+#define GAHBCFG_HBstLen_Incr8			(0x5 << 1)
+#define GAHBCFG_HBstLen_Incr16			(0x7 << 1)
+#define GAHBCFG_GlblIntrEn			(1 << 0)
+
+#define GUSBCFG				HSOTG_REG(0x00C)
+#define GUSBCFG_PHYLPClkSel			(1 << 15)
+#define GUSBCFG_HNPCap				(1 << 9)
+#define GUSBCFG_SRPCap				(1 << 8)
+#define GUSBCFG_PHYIf16			(1 << 3)
+#define GUSBCFG_TOutCal_MASK			(0x7 << 0)
+#define GUSBCFG_TOutCal_SHIFT			(0)
+#define GUSBCFG_TOutCal_LIMIT			(0x7)
+#define GUSBCFG_TOutCal(_x)			((_x) << 0)
+
+#define GRSTCTL				HSOTG_REG(0x010)
+
+#define GRSTCTL_AHBIdle			(1 << 31)
+#define GRSTCTL_DMAReq				(1 << 30)
+#define GRSTCTL_TxFNum_MASK			(0x1f << 6)
+#define GRSTCTL_TxFNum_SHIFT			(6)
+#define GRSTCTL_TxFNum_LIMIT			(0x1f)
+#define GRSTCTL_TxFNum(_x)			((_x) << 6)
+#define GRSTCTL_TxFFlsh			(1 << 5)
+#define GRSTCTL_RxFFlsh			(1 << 4)
+#define GRSTCTL_INTknQFlsh			(1 << 3)
+#define GRSTCTL_FrmCntrRst			(1 << 2)
+#define GRSTCTL_HSftRst			(1 << 1)
+#define GRSTCTL_CSftRst			(1 << 0)
+
+#define GINTSTS				HSOTG_REG(0x014)
+#define GINTMSK				HSOTG_REG(0x018)
+
+#define GINTSTS_WkUpInt			(1 << 31)
+#define GINTSTS_SessReqInt			(1 << 30)
+#define GINTSTS_DisconnInt			(1 << 29)
+#define GINTSTS_ConIDStsChng			(1 << 28)
+#define GINTSTS_PTxFEmp			(1 << 26)
+#define GINTSTS_HChInt				(1 << 25)
+#define GINTSTS_PrtInt				(1 << 24)
+#define GINTSTS_FetSusp			(1 << 22)
+#define GINTSTS_incompIP			(1 << 21)
+#define GINTSTS_IncomplSOIN			(1 << 20)
+#define GINTSTS_OEPInt				(1 << 19)
+#define GINTSTS_IEPInt				(1 << 18)
+#define GINTSTS_EPMis				(1 << 17)
+#define GINTSTS_EOPF				(1 << 15)
+#define GINTSTS_ISOutDrop			(1 << 14)
+#define GINTSTS_EnumDone			(1 << 13)
+#define GINTSTS_USBRst				(1 << 12)
+#define GINTSTS_USBSusp			(1 << 11)
+#define GINTSTS_ErlySusp			(1 << 10)
+#define GINTSTS_GOUTNakEff			(1 << 7)
+#define GINTSTS_GINNakEff			(1 << 6)
+#define GINTSTS_NPTxFEmp			(1 << 5)
+#define GINTSTS_RxFLvl				(1 << 4)
+#define GINTSTS_SOF				(1 << 3)
+#define GINTSTS_OTGInt				(1 << 2)
+#define GINTSTS_ModeMis			(1 << 1)
+#define GINTSTS_CurMod_Host			(1 << 0)
+
+#define GRXSTSR				HSOTG_REG(0x01C)
+#define GRXSTSP				HSOTG_REG(0x020)
+
+#define GRXSTS_FN_MASK				(0x7f << 25)
+#define GRXSTS_FN_SHIFT			(25)
+
+#define GRXSTS_PktSts_MASK			(0xf << 17)
+#define GRXSTS_PktSts_SHIFT			(17)
+#define GRXSTS_PktSts_GlobalOutNAK		(0x1 << 17)
+#define GRXSTS_PktSts_OutRX			(0x2 << 17)
+#define GRXSTS_PktSts_OutDone			(0x3 << 17)
+#define GRXSTS_PktSts_SetupDone		(0x4 << 17)
+#define GRXSTS_PktSts_SetupRX			(0x6 << 17)
+
+#define GRXSTS_DPID_MASK			(0x3 << 15)
+#define GRXSTS_DPID_SHIFT			(15)
+#define GRXSTS_ByteCnt_MASK			(0x7ff << 4)
+#define GRXSTS_ByteCnt_SHIFT			(4)
+#define GRXSTS_EPNum_MASK			(0xf << 0)
+#define GRXSTS_EPNum_SHIFT			(0)
+
+#define GRXFSIZ				HSOTG_REG(0x024)
+
+#define GNPTXFSIZ				HSOTG_REG(0x028)
+
+#define GNPTXFSIZ_NPTxFDep_MASK		(0xffff << 16)
+#define GNPTXFSIZ_NPTxFDep_SHIFT		(16)
+#define GNPTXFSIZ_NPTxFDep_LIMIT		(0xffff)
+#define GNPTXFSIZ_NPTxFDep(_x)			((_x) << 16)
+#define GNPTXFSIZ_NPTxFStAddr_MASK		(0xffff << 0)
+#define GNPTXFSIZ_NPTxFStAddr_SHIFT		(0)
+#define GNPTXFSIZ_NPTxFStAddr_LIMIT		(0xffff)
+#define GNPTXFSIZ_NPTxFStAddr(_x)		((_x) << 0)
+
+#define GNPTXSTS				HSOTG_REG(0x02C)
+
+#define GNPTXSTS_NPtxQTop_MASK			(0x7f << 24)
+#define GNPTXSTS_NPtxQTop_SHIFT		(24)
+
+#define GNPTXSTS_NPTxQSpcAvail_MASK		(0xff << 16)
+#define GNPTXSTS_NPTxQSpcAvail_SHIFT		(16)
+#define GNPTXSTS_NPTxQSpcAvail_GET(_v)		(((_v) >> 16) & 0xff)
+
+#define GNPTXSTS_NPTxFSpcAvail_MASK		(0xffff << 0)
+#define GNPTXSTS_NPTxFSpcAvail_SHIFT		(0)
+#define GNPTXSTS_NPTxFSpcAvail_GET(_v)		(((_v) >> 0) & 0xffff)
+
+
+#define HPTXFSIZ				HSOTG_REG(0x100)
+
+#define DPTXFSIZn(_a)		HSOTG_REG(0x104 + (((_a) - 1) * 4))
+
+#define DPTXFSIZn_DPTxFSize_MASK		(0xffff << 16)
+#define DPTXFSIZn_DPTxFSize_SHIFT		(16)
+#define DPTXFSIZn_DPTxFSize_GET(_v)		(((_v) >> 16) & 0xffff)
+#define DPTXFSIZn_DPTxFSize_LIMIT		(0xffff)
+#define DPTXFSIZn_DPTxFSize(_x)		((_x) << 16)
+
+#define DPTXFSIZn_DPTxFStAddr_MASK		(0xffff << 0)
+#define DPTXFSIZn_DPTxFStAddr_SHIFT		(0)
+
+/* Device mode registers */
+#define DCFG					HSOTG_REG(0x800)
+
+#define DCFG_EPMisCnt_MASK			(0x1f << 18)
+#define DCFG_EPMisCnt_SHIFT			(18)
+#define DCFG_EPMisCnt_LIMIT			(0x1f)
+#define DCFG_EPMisCnt(_x)			((_x) << 18)
+
+#define DCFG_PerFrInt_MASK			(0x3 << 11)
+#define DCFG_PerFrInt_SHIFT			(11)
+#define DCFG_PerFrInt_LIMIT			(0x3)
+#define DCFG_PerFrInt(_x)			((_x) << 11)
+
+#define DCFG_DevAddr_MASK			(0x7f << 4)
+#define DCFG_DevAddr_SHIFT			(4)
+#define DCFG_DevAddr_LIMIT			(0x7f)
+#define DCFG_DevAddr(_x)			((_x) << 4)
+
+#define DCFG_NZStsOUTHShk			(1 << 2)
+
+#define DCFG_DevSpd_MASK			(0x3 << 0)
+#define DCFG_DevSpd_SHIFT			(0)
+#define DCFG_DevSpd_HS				(0x0 << 0)
+#define DCFG_DevSpd_FS				(0x1 << 0)
+#define DCFG_DevSpd_LS				(0x2 << 0)
+#define DCFG_DevSpd_FS48			(0x3 << 0)
+
+#define DCTL					HSOTG_REG(0x804)
+
+#define DCTL_PWROnPrgDone			(1 << 11)
+#define DCTL_CGOUTNak				(1 << 10)
+#define DCTL_SGOUTNak				(1 << 9)
+#define DCTL_CGNPInNAK				(1 << 8)
+#define DCTL_SGNPInNAK				(1 << 7)
+#define DCTL_TstCtl_MASK			(0x7 << 4)
+#define DCTL_TstCtl_SHIFT			(4)
+#define DCTL_GOUTNakSts			(1 << 3)
+#define DCTL_GNPINNakSts			(1 << 2)
+#define DCTL_SftDiscon				(1 << 1)
+#define DCTL_RmtWkUpSig			(1 << 0)
+
+#define DSTS					HSOTG_REG(0x808)
+
+#define DSTS_SOFFN_MASK			(0x3fff << 8)
+#define DSTS_SOFFN_SHIFT			(8)
+#define DSTS_SOFFN_LIMIT			(0x3fff)
+#define DSTS_SOFFN(_x)				((_x) << 8)
+#define DSTS_ErraticErr			(1 << 3)
+#define DSTS_EnumSpd_MASK			(0x3 << 1)
+#define DSTS_EnumSpd_SHIFT			(1)
+#define DSTS_EnumSpd_HS			(0x0 << 1)
+#define DSTS_EnumSpd_FS			(0x1 << 1)
+#define DSTS_EnumSpd_LS			(0x2 << 1)
+#define DSTS_EnumSpd_FS48			(0x3 << 1)
+
+#define DSTS_SuspSts				(1 << 0)
+
+#define DIEPMSK				HSOTG_REG(0x810)
+
+#define DIEPMSK_TxFIFOEmpty			(1 << 7)
+#define DIEPMSK_INEPNakEffMsk			(1 << 6)
+#define DIEPMSK_INTknEPMisMsk			(1 << 5)
+#define DIEPMSK_INTknTXFEmpMsk			(1 << 4)
+#define DIEPMSK_TimeOUTMsk			(1 << 3)
+#define DIEPMSK_AHBErrMsk			(1 << 2)
+#define DIEPMSK_EPDisbldMsk			(1 << 1)
+#define DIEPMSK_XferComplMsk			(1 << 0)
+
+#define DOEPMSK				HSOTG_REG(0x814)
+
+#define DOEPMSK_Back2BackSetup			(1 << 6)
+#define DOEPMSK_OUTTknEPdisMsk			(1 << 4)
+#define DOEPMSK_SetupMsk			(1 << 3)
+#define DOEPMSK_AHBErrMsk			(1 << 2)
+#define DOEPMSK_EPDisbldMsk			(1 << 1)
+#define DOEPMSK_XferComplMsk			(1 << 0)
+
+#define DAINT					HSOTG_REG(0x818)
+#define DAINTMSK				HSOTG_REG(0x81C)
+
+#define DAINT_OutEP_SHIFT			(16)
+#define DAINT_OutEP(x)				(1 << ((x) + 16))
+#define DAINT_InEP(x)				(1 << (x))
+
+#define DTKNQR1				HSOTG_REG(0x820)
+#define DTKNQR2				HSOTG_REG(0x824)
+#define DTKNQR3				HSOTG_REG(0x830)
+#define DTKNQR4				HSOTG_REG(0x834)
+
+#define DVBUSDIS				HSOTG_REG(0x828)
+#define DVBUSPULSE				HSOTG_REG(0x82C)
+
+#define DIEPCTL0				HSOTG_REG(0x900)
+#define DOEPCTL0				HSOTG_REG(0xB00)
+#define DIEPCTL(_a)			HSOTG_REG(0x900 + ((_a) * 0x20))
+#define DOEPCTL(_a)			HSOTG_REG(0xB00 + ((_a) * 0x20))
+
+/* EP0 specialness:
+ * bits[29..28] - reserved (no SetD0PID, SetD1PID)
+ * bits[25..22] - should always be zero, this isn't a periodic endpoint
+ * bits[10..0] - MPS setting differenct for EP0
+ */
+#define D0EPCTL_MPS_MASK			(0x3 << 0)
+#define D0EPCTL_MPS_SHIFT			(0)
+#define D0EPCTL_MPS_64				(0x0 << 0)
+#define D0EPCTL_MPS_32				(0x1 << 0)
+#define D0EPCTL_MPS_16				(0x2 << 0)
+#define D0EPCTL_MPS_8				(0x3 << 0)
+
+#define DxEPCTL_EPEna				(1 << 31)
+#define DxEPCTL_EPDis				(1 << 30)
+#define DxEPCTL_SetD1PID			(1 << 29)
+#define DxEPCTL_SetOddFr			(1 << 29)
+#define DxEPCTL_SetD0PID			(1 << 28)
+#define DxEPCTL_SetEvenFr			(1 << 28)
+#define DxEPCTL_SNAK				(1 << 27)
+#define DxEPCTL_CNAK				(1 << 26)
+#define DxEPCTL_TxFNum_MASK			(0xf << 22)
+#define DxEPCTL_TxFNum_SHIFT			(22)
+#define DxEPCTL_TxFNum_LIMIT			(0xf)
+#define DxEPCTL_TxFNum(_x)			((_x) << 22)
+
+#define DxEPCTL_Stall				(1 << 21)
+#define DxEPCTL_Snp				(1 << 20)
+#define DxEPCTL_EPType_MASK			(0x3 << 18)
+#define DxEPCTL_EPType_SHIFT			(18)
+#define DxEPCTL_EPType_Control			(0x0 << 18)
+#define DxEPCTL_EPType_Iso			(0x1 << 18)
+#define DxEPCTL_EPType_Bulk			(0x2 << 18)
+#define DxEPCTL_EPType_Intterupt		(0x3 << 18)
+
+#define DxEPCTL_NAKsts				(1 << 17)
+#define DxEPCTL_DPID				(1 << 16)
+#define DxEPCTL_EOFrNum			(1 << 16)
+#define DxEPCTL_USBActEp			(1 << 15)
+#define DxEPCTL_NextEp_MASK			(0xf << 11)
+#define DxEPCTL_NextEp_SHIFT			(11)
+#define DxEPCTL_NextEp_LIMIT			(0xf)
+#define DxEPCTL_NextEp(_x)			((_x) << 11)
+
+#define DxEPCTL_MPS_MASK			(0x7ff << 0)
+#define DxEPCTL_MPS_SHIFT			(0)
+#define DxEPCTL_MPS_LIMIT			(0x7ff)
+#define DxEPCTL_MPS(_x)			((_x) << 0)
+
+#define DIEPINT(_a)			HSOTG_REG(0x908 + ((_a) * 0x20))
+#define DOEPINT(_a)			HSOTG_REG(0xB08 + ((_a) * 0x20))
+
+#define DxEPINT_INEPNakEff			(1 << 6)
+#define DxEPINT_Back2BackSetup			(1 << 6)
+#define DxEPINT_INTknEPMis			(1 << 5)
+#define DxEPINT_INTknTXFEmp			(1 << 4)
+#define DxEPINT_OUTTknEPdis			(1 << 4)
+#define DxEPINT_Timeout			(1 << 3)
+#define DxEPINT_Setup				(1 << 3)
+#define DxEPINT_AHBErr				(1 << 2)
+#define DxEPINT_EPDisbld			(1 << 1)
+#define DxEPINT_XferCompl			(1 << 0)
+
+#define DIEPTSIZ0				HSOTG_REG(0x910)
+
+#define DIEPTSIZ0_PktCnt_MASK			(0x3 << 19)
+#define DIEPTSIZ0_PktCnt_SHIFT			(19)
+#define DIEPTSIZ0_PktCnt_LIMIT			(0x3)
+#define DIEPTSIZ0_PktCnt(_x)			((_x) << 19)
+
+#define DIEPTSIZ0_XferSize_MASK		(0x7f << 0)
+#define DIEPTSIZ0_XferSize_SHIFT		(0)
+#define DIEPTSIZ0_XferSize_LIMIT		(0x7f)
+#define DIEPTSIZ0_XferSize(_x)			((_x) << 0)
+
+#define DOEPTSIZ0				HSOTG_REG(0xB10)
+#define DOEPTSIZ0_SUPCnt_MASK			(0x3 << 29)
+#define DOEPTSIZ0_SUPCnt_SHIFT			(29)
+#define DOEPTSIZ0_SUPCnt_LIMIT			(0x3)
+#define DOEPTSIZ0_SUPCnt(_x)			((_x) << 29)
+
+#define DOEPTSIZ0_PktCnt			(1 << 19)
+#define DOEPTSIZ0_XferSize_MASK		(0x7f << 0)
+#define DOEPTSIZ0_XferSize_SHIFT		(0)
+
+#define DIEPTSIZ(_a)			HSOTG_REG(0x910 + ((_a) * 0x20))
+#define DOEPTSIZ(_a)			HSOTG_REG(0xB10 + ((_a) * 0x20))
+
+#define DxEPTSIZ_MC_MASK			(0x3 << 29)
+#define DxEPTSIZ_MC_SHIFT			(29)
+#define DxEPTSIZ_MC_LIMIT			(0x3)
+#define DxEPTSIZ_MC(_x)			((_x) << 29)
+
+#define DxEPTSIZ_PktCnt_MASK			(0x3ff << 19)
+#define DxEPTSIZ_PktCnt_SHIFT			(19)
+#define DxEPTSIZ_PktCnt_GET(_v)		(((_v) >> 19) & 0x3ff)
+#define DxEPTSIZ_PktCnt_LIMIT			(0x3ff)
+#define DxEPTSIZ_PktCnt(_x)			((_x) << 19)
+
+#define DxEPTSIZ_XferSize_MASK			(0x7ffff << 0)
+#define DxEPTSIZ_XferSize_SHIFT		(0)
+#define DxEPTSIZ_XferSize_GET(_v)		(((_v) >> 0) & 0x7ffff)
+#define DxEPTSIZ_XferSize_LIMIT		(0x7ffff)
+#define DxEPTSIZ_XferSize(_x)			((_x) << 0)
+
+#define DIEPDMA(_a)			HSOTG_REG(0x914 + ((_a) * 0x20))
+#define DOEPDMA(_a)			HSOTG_REG(0xB14 + ((_a) * 0x20))
+#define DTXFSTS(_a)			HSOTG_REG(0x918 + ((_a) * 0x20))
+
+#define EPFIFO(_a)			HSOTG_REG(0x1000 + ((_a) * 0x1000))
+
+#endif /* __REGS_USB_HSOTG_H */
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index cef9b82ff911..36c6836eeb0f 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -110,7 +110,6 @@ struct s3c_hsudc_ep {
 	struct usb_ep ep;
 	char name[20];
 	struct s3c_hsudc *dev;
-	const struct usb_endpoint_descriptor *desc;
 	struct list_head queue;
 	u8 stopped;
 	u8 wedge;
@@ -761,7 +760,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
 	u32 ecr = 0;
 
 	hsep = our_ep(_ep);
-	if (!_ep || !desc || hsep->desc || _ep->name == ep0name
+	if (!_ep || !desc || hsep->ep.desc || _ep->name == ep0name
 		|| desc->bDescriptorType != USB_DT_ENDPOINT
 		|| hsep->bEndpointAddress != desc->bEndpointAddress
 		|| ep_maxpacket(hsep) < usb_endpoint_maxp(desc))
@@ -783,7 +782,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep,
 	writel(ecr, hsudc->regs + S3C_ECR);
 
 	hsep->stopped = hsep->wedge = 0;
-	hsep->desc = desc;
+	hsep->ep.desc = desc;
 	hsep->ep.maxpacket = usb_endpoint_maxp(desc);
 
 	s3c_hsudc_set_halt(_ep, 0);
@@ -806,7 +805,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
 	struct s3c_hsudc *hsudc = hsep->dev;
 	unsigned long flags;
 
-	if (!_ep || !hsep->desc)
+	if (!_ep || !hsep->ep.desc)
 		return -EINVAL;
 
 	spin_lock_irqsave(&hsudc->lock, flags);
@@ -816,7 +815,6 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep)
 
 	s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
 
-	hsep->desc = 0;
 	hsep->ep.desc = NULL;
 	hsep->stopped = 1;
 
@@ -1006,7 +1004,6 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
 	hsep->ep.maxpacket = epnum ? 512 : 64;
 	hsep->ep.ops = &s3c_hsudc_ep_ops;
 	hsep->fifo = hsudc->regs + S3C_BR(epnum);
-	hsep->desc = 0;
 	hsep->ep.desc = NULL;
 	hsep->stopped = 0;
 	hsep->wedge = 0;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 195524cde6c3..3de71d37d75e 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1062,7 +1062,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
 
 	ep = to_s3c2410_ep(_ep);
 
-	if (!_ep || !desc || ep->desc
+	if (!_ep || !desc || ep->ep.desc
 			|| _ep->name == ep0name
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
@@ -1075,7 +1075,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
 
 	local_irq_save (flags);
 	_ep->maxpacket = max & 0x7ff;
-	ep->desc = desc;
+	ep->ep.desc = desc;
 	ep->halted = 0;
 	ep->bEndpointAddress = desc->bEndpointAddress;
 
@@ -1136,7 +1136,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
 	unsigned long flags;
 	u32 int_en_reg;
 
-	if (!_ep || !ep->desc) {
+	if (!_ep || !ep->ep.desc) {
 		dprintk(DEBUG_NORMAL, "%s not enabled\n",
 			_ep ? ep->ep.name : NULL);
 		return -EINVAL;
@@ -1146,7 +1146,6 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
 
 	dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
 
-	ep->desc = NULL;
 	ep->ep.desc = NULL;
 	ep->halted = 1;
 
@@ -1195,7 +1194,7 @@ s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
 
 	dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
 
-	if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
+	if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name))
 		return;
 
 	WARN_ON (!list_empty (&req->queue));
@@ -1215,7 +1214,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
 	int			fifo_count = 0;
 	unsigned long		flags;
 
-	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+	if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
 		dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
 		return -EINVAL;
 	}
@@ -1363,7 +1362,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
 	unsigned long		flags;
 	u32			idx;
 
-	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+	if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) {
 		dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
 		return -EINVAL;
 	}
@@ -1629,7 +1628,6 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
 			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
 
 		ep->dev = dev;
-		ep->desc = NULL;
 		ep->ep.desc = NULL;
 		ep->halted = 0;
 		INIT_LIST_HEAD (&ep->queue);
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h
index 1653bae08b80..3e80fd5c820f 100644
--- a/drivers/usb/gadget/s3c2410_udc.h
+++ b/drivers/usb/gadget/s3c2410_udc.h
@@ -19,7 +19,6 @@ struct s3c2410_ep {
 	unsigned long			last_io;	/* jiffies timestamp */
 	struct usb_gadget		*gadget;
 	struct s3c2410_udc		*dev;
-	const struct usb_endpoint_descriptor *desc;
 	struct usb_ep			ep;
 	u8				num;
 
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 31d34832907e..12ad516ada77 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -72,7 +72,7 @@
 
 static const char longname[] = "Gadget Zero";
 
-unsigned buflen = 4096;
+unsigned buflen = 4096;		/* only used for bulk endpoints */
 module_param(buflen, uint, 0);
 
 /*
@@ -170,14 +170,17 @@ static struct usb_gadget_strings *dev_strings[] = {
 
 /*-------------------------------------------------------------------------*/
 
-struct usb_request *alloc_ep_req(struct usb_ep *ep)
+struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
 {
 	struct usb_request	*req;
 
 	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
 	if (req) {
-		req->length = buflen;
-		req->buf = kmalloc(buflen, GFP_ATOMIC);
+		if (len)
+			req->length = len;
+		else
+			req->length = buflen;
+		req->buf = kmalloc(req->length, GFP_ATOMIC);
 		if (!req->buf) {
 			usb_ep_free_request(ep, req);
 			req = NULL;
@@ -206,10 +209,15 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
 }
 
 void disable_endpoints(struct usb_composite_dev *cdev,
-		struct usb_ep *in, struct usb_ep *out)
+		struct usb_ep *in, struct usb_ep *out,
+		struct usb_ep *iso_in, struct usb_ep *iso_out)
 {
 	disable_ep(cdev, in);
 	disable_ep(cdev, out);
+	if (iso_in)
+		disable_ep(cdev, iso_in);
+	if (iso_out)
+		disable_ep(cdev, iso_out);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -311,7 +319,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
 		device_desc.bcdDevice = cpu_to_le16(0x9999);
 	}
 
-
 	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
 
 	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 00bd2a5e0362..28478ce26c34 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -55,6 +55,7 @@ struct usbhsg_gpriv {
 #define USBHSG_STATUS_STARTED		(1 << 0)
 #define USBHSG_STATUS_REGISTERD		(1 << 1)
 #define USBHSG_STATUS_WEDGE		(1 << 2)
+#define USBHSG_STATUS_SELF_POWERED	(1 << 3)
 };
 
 struct usbhsg_recip_handle {
@@ -333,7 +334,10 @@ static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv,
 					       struct usb_ctrlrequest *ctrl)
 {
 	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	unsigned short status = 1 << USB_DEVICE_SELF_POWERED;
+	unsigned short status = 0;
+
+	if (usbhsg_status_has(gpriv, USBHSG_STATUS_SELF_POWERED))
+		status = 1 << USB_DEVICE_SELF_POWERED;
 
 	__usbhsg_recip_send_status(gpriv, status);
 
@@ -879,8 +883,21 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
 	return usbhs_frame_get_num(priv);
 }
 
+static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
+{
+	struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+
+	if (is_self)
+		usbhsg_status_set(gpriv, USBHSG_STATUS_SELF_POWERED);
+	else
+		usbhsg_status_clr(gpriv, USBHSG_STATUS_SELF_POWERED);
+
+	return 0;
+}
+
 static struct usb_gadget_ops usbhsg_gadget_ops = {
 	.get_frame		= usbhsg_get_frame,
+	.set_selfpowered	= usbhsg_set_selfpowered,
 	.udc_start		= usbhsg_gadget_start,
 	.udc_stop		= usbhsg_gadget_stop,
 };
diff --git a/arch/arm/plat-samsung/include/plat/udc-hs.h b/include/linux/platform_data/s3c-hsotg.h
similarity index 90%
rename from arch/arm/plat-samsung/include/plat/udc-hs.h
rename to include/linux/platform_data/s3c-hsotg.h
index c9e3667cb2b1..97ec12c2ded4 100644
--- a/arch/arm/plat-samsung/include/plat/udc-hs.h
+++ b/include/linux/platform_data/s3c-hsotg.h
@@ -1,4 +1,4 @@
-/* arch/arm/plat-s3c/include/plat/udc-hs.h
+/* include/linux/platform_data/s3c-hsotg.h
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
@@ -25,7 +25,8 @@ enum s3c_hsotg_dmamode {
  */
 struct s3c_hsotg_plat {
 	enum s3c_hsotg_dmamode	dma;
-	unsigned int		is_osc : 1;
+	unsigned int		is_osc:1;
+	int                     phy_type;
 
 	int (*phy_init)(struct platform_device *pdev, int type);
 	int (*phy_exit)(struct platform_device *pdev, int type);