drivers: usb: mtu3: Integrate the Linux kernel driver to U-Boot

This updates the driver to work in U-boot.
Currently, this only work in PIO mode, and only device mode
is currently supported.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
diff --git a/Makefile b/Makefile
index 54da5cd..c8f3330 100644
--- a/Makefile
+++ b/Makefile
@@ -729,6 +729,7 @@
 libs-$(CONFIG_$(SPL_)ALTERA_SDRAM) += drivers/ddr/altera/
 libs-y += drivers/serial/
 libs-y += drivers/usb/dwc3/
+libs-y += drivers/usb/mtu3/
 libs-y += drivers/usb/common/
 libs-y += drivers/usb/emul/
 libs-y += drivers/usb/eth/
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 3b53bf2..86bb82e 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -80,6 +80,8 @@
 
 source "drivers/usb/ulpi/Kconfig"
 
+source "drivers/usb/mtu3/Kconfig"
+
 comment "USB peripherals"
 
 config USB_STORAGE
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig
index fe58904..9a59baa 100644
--- a/drivers/usb/mtu3/Kconfig
+++ b/drivers/usb/mtu3/Kconfig
@@ -1,11 +1,17 @@
 # For MTK USB3.0 IP
 
+config USB_MTU3_GADGET
+	bool
+
 config USB_MTU3
 	tristate "MediaTek USB3 Dual Role controller"
 	depends on USB || USB_GADGET
 	depends on ARCH_MEDIATEK || COMPILE_TEST
-	depends on EXTCON || !EXTCON
+	depends on DM_USB
+	select OF_LIVE
 	select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD
+	select USB_MTU3_GADGET
+	select USB_GADGET_DUALSPEED
 	help
 	  Say Y or M here if your system runs on MediaTek SoCs with
 	  Dual Role SuperSpeed USB controller. You can select usb
@@ -15,42 +21,3 @@
 
 	  Choose M here to compile this driver as a module, and it
 	  will be called mtu3.ko.
-
-
-if USB_MTU3
-choice
-	bool "MTU3 Mode Selection"
-	default USB_MTU3_DUAL_ROLE if (USB && USB_GADGET)
-	default USB_MTU3_HOST if (USB && !USB_GADGET)
-	default USB_MTU3_GADGET if (!USB && USB_GADGET)
-
-config USB_MTU3_HOST
-	bool "Host only mode"
-	depends on USB=y || USB=USB_MTU3
-	help
-	  Select this when you want to use MTU3 in host mode only,
-	  thereby the gadget feature will be regressed.
-
-config USB_MTU3_GADGET
-	bool "Gadget only mode"
-	depends on USB_GADGET=y || USB_GADGET=USB_MTU3
-	help
-	  Select this when you want to use MTU3 in gadget mode only,
-	  thereby the host feature will be regressed.
-
-config USB_MTU3_DUAL_ROLE
-	bool "Dual Role mode"
-	depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3))
-	depends on (EXTCON=y || EXTCON=USB_MTU3)
-	help
-	  This is the default mode of working of MTU3 controller where
-	  both host and gadget features are enabled.
-
-endchoice
-
-config USB_MTU3_DEBUG
-	bool "Enable Debugging Messages"
-	help
-	  Say Y here to enable debugging messages in the MTU3 Driver.
-
-endif
diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile
index 3bf8cbc..3619d85 100644
--- a/drivers/usb/mtu3/Makefile
+++ b/drivers/usb/mtu3/Makefile
@@ -1,30 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
-ccflags-$(CONFIG_USB_MTU3_DEBUG)	+= -DDEBUG
-
-# define_trace.h needs to know how to find our header
-CFLAGS_mtu3_trace.o	:= -I$(src)
-
 obj-$(CONFIG_USB_MTU3)	+= mtu3.o
 
-mtu3-y	:= mtu3_plat.o
-
-ifneq ($(CONFIG_TRACING),)
-	mtu3-y	+= mtu3_trace.o
-endif
-
-ifneq ($(filter y,$(CONFIG_USB_MTU3_HOST) $(CONFIG_USB_MTU3_DUAL_ROLE)),)
-	mtu3-y	+= mtu3_host.o
-endif
-
-ifneq ($(filter y,$(CONFIG_USB_MTU3_GADGET) $(CONFIG_USB_MTU3_DUAL_ROLE)),)
-	mtu3-y	+= mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o mtu3_qmu.o
-endif
-
-ifneq ($(CONFIG_USB_MTU3_DUAL_ROLE),)
-	mtu3-y	+= mtu3_dr.o
-endif
-
-ifneq ($(CONFIG_DEBUG_FS),)
-	mtu3-y	+= mtu3_debugfs.o
-endif
+mtu3-y += mtu3_gadget.o mtu3_gadget_ep0.o mtu3_core.o mtu3_plat.o
+mtu3-$(CONFIG_MTU3_QMU) += mtu3_qmu.o
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index 6fc4744..d5819db 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -10,14 +10,9 @@
 #ifndef __MTU3_H__
 #define __MTU3_H__
 
-#include <linux/device.h>
-#include <linux/dmapool.h>
-#include <linux/extcon.h>
-#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <dm.h>
 #include <linux/list.h>
-#include <linux/phy/phy.h>
-#include <linux/regulator/consumer.h>
-#include <linux/usb.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
@@ -36,6 +31,7 @@
 #define	MU3D_EP_RXCR0(epnum)	(U3D_RX1CSR0 + (((epnum) - 1) * 0x10))
 #define	MU3D_EP_RXCR1(epnum)	(U3D_RX1CSR1 + (((epnum) - 1) * 0x10))
 #define	MU3D_EP_RXCR2(epnum)	(U3D_RX1CSR2 + (((epnum) - 1) * 0x10))
+#define	MU3D_EP_RXCR3(epnum)	(U3D_RX1CSR3 + (((epnum) - 1) * 0x10))
 
 #define USB_QMU_TQHIAR(epnum)	(U3D_TXQHIAR1 + (((epnum) - 1) * 0x4))
 #define USB_QMU_RQHIAR(epnum)	(U3D_RXQHIAR1 + (((epnum) - 1) * 0x4))
@@ -240,7 +236,7 @@
  * @uwk_vers: the version of the wakeup glue layer
  */
 struct ssusb_mtk {
-	struct device *dev;
+	struct udevice *dev;
 	struct mtu3 *u3d;
 	void __iomem *mac_base;
 	void __iomem *ippc_base;
@@ -307,9 +303,9 @@
 	int epnum;
 };
 
-static inline struct ssusb_mtk *dev_to_ssusb(struct device *dev)
+static inline struct ssusb_mtk *dev_to_ssusb(struct udevice *dev)
 {
-	return dev_get_drvdata(dev);
+	return dev_get_priv(dev);
 }
 
 /**
@@ -327,7 +323,7 @@
 struct mtu3 {
 	spinlock_t lock;
 	struct ssusb_mtk *ssusb;
-	struct device *dev;
+	struct udevice *dev;
 	void __iomem *mac_base;
 	void __iomem *ippc_base;
 	int irq;
@@ -444,6 +440,24 @@
 void mtu3_gadget_disconnect(struct mtu3 *mtu);
 
 irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu);
+irqreturn_t mtu3_ep_isr(struct mtu3 *mtu);
 extern const struct usb_ep_ops mtu3_ep0_ops;
 
+/* Compat with uboot driver */
+#define trace_mtu3_alloc_request(mreq)
+#define trace_mtu3_free_request(mreq)
+#define trace_mtu3_gadget_queue(mreq)
+#define trace_mtu3_gadget_dequeue(mreq)
+#define trace_mtu3_handle_setup(mreq)
+#define mtu3_dbg_trace(dev, format, ...)
+#define trace_mtu3_gadget_ep_set_halt(mep)
+#define trace_mtu3_prepare_gpd(mep, gpd)
+#define trace_mtu3_zlp_exp_gpd(mep, gpd)
+#define trace_mtu3_complete_gpd(mep, gpd)
+#define trace_mtu3_qmu_isr(done_status, status)
+#define trace_mtu3_u3_ltssm_isr(ltssm)
+#define trace_mtu3_u2_common_isr(u2comm)
+#define trace_mtu3_req_complete(mreq)
+#define trace_mtu3_gadget_ep_disable(mep)
+#define trace_mtu3_gadget_ep_enable(mep)
 #endif
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c
index 1819f9e..0894c4c 100644
--- a/drivers/usb/mtu3/mtu3_core.c
+++ b/drivers/usb/mtu3/mtu3_core.c
@@ -8,16 +8,14 @@
  * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
  */
 
-#include <linux/dma-mapping.h>
+#include <dm.h>
+#include <linux/bitmap.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
+#include <linux/log2.h>
+#include <linux/usb/gadget.h>
 
 #include "mtu3.h"
-#include "mtu3_debug.h"
-#include "mtu3_trace.h"
+#include "mtu3_dr.h"
 
 static int ep_fifo_alloc(struct mtu3_ep *mep, u32 seg_size)
 {
@@ -178,7 +176,10 @@
 	u32 value;
 
 	/*Enable level 1 interrupts (BMU, QMU, MAC3, DMA, MAC2, EPCTL) */
-	value = BMU_INTR | QMU_INTR | MAC3_INTR | MAC2_INTR | EP_CTRL_INTR;
+	value = BMU_INTR | MAC3_INTR | MAC2_INTR | EP_CTRL_INTR;
+#ifdef CONFIG_MTU3_QMU
+	value |= QMU_INTR
+#endif
 	mtu3_writel(mbase, U3D_LV1IESR, value);
 
 	/* Enable U2 common USB interrupts */
@@ -192,10 +193,12 @@
 		mtu3_writel(mbase, U3D_LTSSM_INTR_ENABLE, value);
 	}
 
+#ifdef CONFIG_MTU3_QMU
 	/* Enable QMU interrupts. */
 	value = TXQ_CSERR_INT | TXQ_LENERR_INT | RXQ_CSERR_INT |
 			RXQ_LENERR_INT | RXQ_ZLPERR_INT;
 	mtu3_writel(mbase, U3D_QIESR1, value);
+#endif
 
 	/* Enable speed change interrupt */
 	mtu3_writel(mbase, U3D_DEV_LINK_INTR_ENABLE, SSUSB_DEV_SPEED_CHG_INTR);
@@ -318,8 +321,9 @@
 
 	if (mep->is_in) {
 		csr0 = TX_TXMAXPKTSZ(mep->maxp);
+#ifdef CONFIG_MTU3_QMU
 		csr0 |= TX_DMAREQEN;
-
+#endif
 		num_pkts = (burst + 1) * (mult + 1) - 1;
 		csr1 = TX_SS_BURST(burst) | TX_SLOT(mep->slot);
 		csr1 |= TX_MAX_PKT(gen2cp, num_pkts) | TX_MULT(gen2cp, mult);
@@ -341,20 +345,28 @@
 			break;
 		}
 
+#ifdef CONFIG_MTU3_QMU
 		/* Enable QMU Done interrupt */
 		mtu3_setbits(mbase, U3D_QIESR0, QMU_TX_DONE_INT(epnum));
+#endif
 
 		mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), csr0);
 		mtu3_writel(mbase, MU3D_EP_TXCR1(epnum), csr1);
 		mtu3_writel(mbase, MU3D_EP_TXCR2(epnum), csr2);
 
+#ifndef CONFIG_MTU3_QMU
+		mtu3_writel(mbase, U3D_EPIESR, BIT(0) << epnum);
+#endif
+
 		dev_dbg(mtu->dev, "U3D_TX%d CSR0:%#x, CSR1:%#x, CSR2:%#x\n",
 			epnum, mtu3_readl(mbase, MU3D_EP_TXCR0(epnum)),
 			mtu3_readl(mbase, MU3D_EP_TXCR1(epnum)),
 			mtu3_readl(mbase, MU3D_EP_TXCR2(epnum)));
 	} else {
 		csr0 = RX_RXMAXPKTSZ(mep->maxp);
+#ifdef CONFIG_MTU3_QMU
 		csr0 |= RX_DMAREQEN;
+#endif
 
 		num_pkts = (burst + 1) * (mult + 1) - 1;
 		csr1 = RX_SS_BURST(burst) | RX_SLOT(mep->slot);
@@ -377,13 +389,19 @@
 			break;
 		}
 
+#ifdef CONFIG_MTU3_QMU
 		/*Enable QMU Done interrupt */
 		mtu3_setbits(mbase, U3D_QIESR0, QMU_RX_DONE_INT(epnum));
+#endif
 
 		mtu3_writel(mbase, MU3D_EP_RXCR0(epnum), csr0);
 		mtu3_writel(mbase, MU3D_EP_RXCR1(epnum), csr1);
 		mtu3_writel(mbase, MU3D_EP_RXCR2(epnum), csr2);
 
+#ifndef CONFIG_MTU3_QMU
+		mtu3_writel(mbase, U3D_EPIESR, BIT(16) << epnum);
+#endif
+
 		dev_dbg(mtu->dev, "U3D_RX%d CSR0:%#x, CSR1:%#x, CSR2:%#x\n",
 			epnum, mtu3_readl(mbase, MU3D_EP_RXCR0(epnum)),
 			mtu3_readl(mbase, MU3D_EP_RXCR1(epnum)),
@@ -408,12 +426,16 @@
 		mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), 0);
 		mtu3_writel(mbase, MU3D_EP_TXCR1(epnum), 0);
 		mtu3_writel(mbase, MU3D_EP_TXCR2(epnum), 0);
+#ifdef CONFIG_MTU3_QMU
 		mtu3_setbits(mbase, U3D_QIECR0, QMU_TX_DONE_INT(epnum));
+#endif
 	} else {
 		mtu3_writel(mbase, MU3D_EP_RXCR0(epnum), 0);
 		mtu3_writel(mbase, MU3D_EP_RXCR1(epnum), 0);
 		mtu3_writel(mbase, MU3D_EP_RXCR2(epnum), 0);
+#ifdef CONFIG_MTU3_QMU
 		mtu3_setbits(mbase, U3D_QIECR0, QMU_RX_DONE_INT(epnum));
+#endif
 	}
 
 	mtu3_ep_reset(mep);
@@ -496,7 +518,7 @@
 	struct mtu3_ep *ep_array;
 	int in_ep_num, out_ep_num;
 	u32 cap_epinfo;
-	int ret;
+	int ret = 0;
 	int i;
 
 	cap_epinfo = mtu3_readl(mbase, U3D_CAP_EPINFO);
@@ -531,16 +553,20 @@
 
 	get_ep_fifo_config(mtu);
 
+#ifdef CONFIG_MTU3_QMU
 	ret = mtu3_qmu_init(mtu);
 	if (ret)
 		kfree(mtu->ep_array);
+#endif
 
 	return ret;
 }
 
 static void mtu3_mem_free(struct mtu3 *mtu)
 {
+#ifdef CONFIG_MTU3_QMU
 	mtu3_qmu_exit(mtu);
+#endif
 	kfree(mtu->ep_array);
 }
 
@@ -748,17 +774,30 @@
 	if (level1 & MAC3_INTR)
 		mtu3_u3_ltssm_isr(mtu);
 
-	if (level1 & BMU_INTR)
+	if (level1 & BMU_INTR) {
+#ifndef CONFIG_MTU3_QMU
+		mtu3_ep_isr(mtu);
+#endif
 		mtu3_ep0_isr(mtu);
+	}
 
+#ifdef CONFIG_MTU3_QMU
 	if (level1 & QMU_INTR)
 		mtu3_qmu_isr(mtu);
+#endif
 
 	spin_unlock_irqrestore(&mtu->lock, flags);
 
 	return IRQ_HANDLED;
 }
 
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+	struct ssusb_mtk *ssusb = dev_get_platdata(dev);
+
+	return mtu3_irq(0, ssusb->u3d);
+}
+
 static int mtu3_hw_init(struct mtu3 *mtu)
 {
 	u32 value;
@@ -797,36 +836,9 @@
 	mtu3_mem_free(mtu);
 }
 
-/**
- * we set 32-bit DMA mask by default, here check whether the controller
- * supports 36-bit DMA or not, if it does, set 36-bit DMA mask.
- */
-static int mtu3_set_dma_mask(struct mtu3 *mtu)
-{
-	struct device *dev = mtu->dev;
-	bool is_36bit = false;
-	int ret = 0;
-	u32 value;
-
-	value = mtu3_readl(mtu->mac_base, U3D_MISC_CTRL);
-	if (value & DMA_ADDR_36BIT) {
-		is_36bit = true;
-		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
-		/* If set 36-bit DMA mask fails, fall back to 32-bit DMA mask */
-		if (ret) {
-			is_36bit = false;
-			ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-		}
-	}
-	dev_info(dev, "dma mask: %s bits\n", is_36bit ? "36" : "32");
-
-	return ret;
-}
-
 int ssusb_gadget_init(struct ssusb_mtk *ssusb)
 {
-	struct device *dev = ssusb->dev;
-	struct platform_device *pdev = to_platform_device(dev);
+	struct udevice *dev = ssusb->dev;
 	struct mtu3 *mtu = NULL;
 	int ret = -ENOMEM;
 
@@ -834,20 +846,17 @@
 	if (mtu == NULL)
 		return -ENOMEM;
 
-	mtu->irq = platform_get_irq(pdev, 0);
-	if (mtu->irq < 0) {
-		dev_err(dev, "fail to get irq number\n");
-		return mtu->irq;
-	}
-	dev_info(dev, "irq %d\n", mtu->irq);
-
 	spin_lock_init(&mtu->lock);
 	mtu->dev = dev;
 	mtu->ippc_base = ssusb->ippc_base;
 	mtu->mac_base = ssusb->mac_base;
 	ssusb->u3d = mtu;
 	mtu->ssusb = ssusb;
-	mtu->max_speed = usb_get_maximum_speed(dev);
+	/*
+	 * FIXME:
+	 * usb_get_maximum_speed doesn't work, use USB_SPEED_HIGH for now
+	 */
+	mtu->max_speed = USB_SPEED_HIGH;
 
 	/* check the max_speed parameter */
 	switch (mtu->max_speed) {
@@ -875,20 +884,6 @@
 		return ret;
 	}
 
-	ret = mtu3_set_dma_mask(mtu);
-	if (ret) {
-		dev_err(dev, "mtu3 set dma_mask failed:%d\n", ret);
-		goto dma_mask_err;
-	}
-
-	ret = devm_request_irq(dev, mtu->irq, mtu3_irq, 0, dev_name(dev), mtu);
-	if (ret) {
-		dev_err(dev, "request irq %d failed!\n", mtu->irq);
-		goto irq_err;
-	}
-
-	device_init_wakeup(dev, true);
-
 	ret = mtu3_gadget_setup(mtu);
 	if (ret) {
 		dev_err(dev, "mtu3 gadget init failed:%d\n", ret);
@@ -899,17 +894,11 @@
 	if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG)
 		mtu3_stop(mtu);
 
-	ssusb_dev_debugfs_init(ssusb);
-
 	dev_dbg(dev, " %s() done...\n", __func__);
 
 	return 0;
 
 gadget_err:
-	device_init_wakeup(dev, false);
-
-dma_mask_err:
-irq_err:
 	mtu3_hw_exit(mtu);
 	ssusb->u3d = NULL;
 	dev_err(dev, " %s() fail...\n", __func__);
@@ -922,6 +911,5 @@
 	struct mtu3 *mtu = ssusb->u3d;
 
 	mtu3_gadget_cleanup(mtu);
-	device_init_wakeup(ssusb->dev, false);
 	mtu3_hw_exit(mtu);
 }
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c
index f93732e..bd1feda 100644
--- a/drivers/usb/mtu3/mtu3_gadget.c
+++ b/drivers/usb/mtu3/mtu3_gadget.c
@@ -7,8 +7,163 @@
  * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
  */
 
+#include <linux/usb/gadget.h>
+
 #include "mtu3.h"
+#ifndef __UBOOT__
 #include "mtu3_trace.h"
+#endif
+
+#ifndef CONFIG_MTU3_QMU
+#define U3D_FIFO(x)         (U3D_FIFO0 + ((x) * 0x10))
+#define USB_FIFO(x)         (U3D_FIFO(x))
+
+
+static void epx_write_fifo(struct mtu3_ep *mep, const u8 *src, u16 len)
+{
+	void __iomem *fifo = mep->mtu->mac_base + USB_FIFO(mep->epnum);
+	u16 index = 0;
+
+	dev_dbg(mep->mtu->dev, "%s: ep%din, len=%d, buf=%p\n",
+		__func__, mep->epnum, len, src);
+
+	if (len >= 4) {
+		iowrite32_rep(fifo, src, len >> 2);
+		index = len & ~0x03;
+	}
+	if (len & 0x02) {
+		writew(*(u16 *)&src[index], fifo);
+		index += 2;
+	}
+	if (len & 0x01)
+		writeb(src[index], fifo);
+}
+
+static void epx_read_fifo(struct mtu3_ep *mep, u8 *dst, u16 len)
+{
+	void __iomem *fifo = mep->mtu->mac_base + USB_FIFO(mep->epnum);
+	u32 value;
+	u16 index = 0;
+
+	dev_dbg(mep->mtu->dev, "%s: ep%dout len=%d buf=%p\n",
+		 __func__, mep->epnum, len, dst);
+
+	if (len >= 4) {
+		ioread32_rep(fifo, dst, len >> 2);
+		index = len & ~0x03;
+	}
+	if (len & 0x3) {
+		value = readl(fifo);
+		memcpy(&dst[index], &value, len & 0x3);
+	}
+
+}
+
+static int ep_write_fifo(struct mtu3_ep *mep, struct usb_request *req)
+{
+	void __iomem *mbase = mep->mtu->mac_base;
+	int epnum = mep->epnum;
+	u32 csr;
+
+	/* udc_endpoint_write: cannot write ep0 */
+	if (epnum == 0)
+		return -EINVAL;
+
+	/* udc_endpoint_write: cannot write USB_DIR_OUT */
+	if (mep->is_in == 0) /* USB_DIR_OUT: val is 0x0; in == 0 here */
+		return EINVAL;
+
+	csr = mtu3_readl(mbase, MU3D_EP_TXCR0(epnum));
+	if (csr & TX_TXPKTRDY) {
+		return -EBUSY;
+	}
+	epx_write_fifo(mep, req->buf, req->length);
+
+	csr |= TX_TXPKTRDY;
+	mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), csr);
+
+	return 0;
+}
+
+irqreturn_t mtu3_epx_isr(struct mtu3 *mtu, struct mtu3_ep *mep)
+{
+	void __iomem *mbase = mtu->mac_base;
+	u8 epnum = mep->epnum;
+	struct usb_request *req = NULL;
+	struct mtu3_request *mreq;
+	u32 csr0, csr3;
+
+	if (!mep->is_in) {
+		csr0 = mtu3_readl(mbase, MU3D_EP_RXCR0(epnum));
+
+		if (csr0 & RX_SENTSTALL) {
+			dev_err(mep->mtu->dev, "EP %d(RX): STALL\n", epnum);
+			return IRQ_HANDLED;
+		}
+
+		if (!(csr0 & RX_RXPKTRDY)) {
+			dev_dbg(mep->mtu->dev, "EP %d: ERRONEOUS INTERRUPT\n", epnum);
+			return IRQ_HANDLED;
+		}
+
+		csr3 = mtu3_readl(mbase, MU3D_EP_RXCR3(epnum));
+		mreq = next_request(mep);
+		req = &mreq->request;
+		req->actual = csr3 >> 16;
+		epx_read_fifo(mep, req->buf, csr3 >> 16);
+
+		csr0 |= RX_RXPKTRDY;
+		mtu3_writel(mbase, MU3D_EP_RXCR0(epnum), csr0);
+		mtu3_req_complete(mep, req, 0);
+	} else {
+		csr0 = mtu3_readl(mbase, MU3D_EP_TXCR0(epnum));
+		mreq = next_request(mep);
+		req = &mreq->request;
+
+		if (csr0 & TX_SENTSTALL) {
+			dev_err(mep->mtu->dev, "EP %d(TX): STALL\n", epnum);
+			mtu3_req_complete(mep, req, -1);
+			return IRQ_HANDLED;
+		}
+
+		if (csr0 & TX_TXPKTRDY) {
+			dev_dbg(mep->mtu->dev, "ep%d is not ready to be written\n", epnum);
+			return IRQ_HANDLED;
+		}
+
+		/* do signaling */
+		mtu3_req_complete(mep, req, 0);
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t mtu3_ep_isr(struct mtu3 *mtu)
+{
+	void __iomem *mbase = mtu->mac_base;
+	u32 int_status;
+	int epnum;
+
+	int_status = mtu3_readl(mbase, U3D_EPISR);
+	int_status &= mtu3_readl(mbase, U3D_EPIER);
+	int_status &= ~(EP0ISR | SETUPENDISR);
+	mtu3_writel(mbase, U3D_EPISR, int_status); /* W1C */
+
+	if (!int_status)
+		return 0;
+
+	for (epnum = 1; epnum < mtu->num_eps; epnum++) {
+		if (int_status & (BIT(16) << epnum))
+			mtu3_epx_isr(mtu, mtu->out_eps + epnum);
+		if (int_status & (BIT(0) << epnum))
+			mtu3_epx_isr(mtu, mtu->in_eps + epnum);
+	}
+
+	return IRQ_HANDLED;
+}
+#endif
 
 void mtu3_req_complete(struct mtu3_ep *mep,
 		     struct usb_request *req, int status)
@@ -53,9 +208,11 @@
 
 	dev_dbg(mep->mtu->dev, "abort %s's req: sts %d\n", mep->name, status);
 
+#ifdef CONFIG_MTU3_QMU
 	/* exclude EP0 */
 	if (mep->epnum)
 		mtu3_qmu_flush(mep);
+#endif
 
 	while (!list_empty(&mep->req_list)) {
 		mreq = list_first_entry(&mep->req_list,
@@ -121,13 +278,17 @@
 	if (ret < 0)
 		return ret;
 
+#ifdef CONFIG_MTU3_QMU
 	ret = mtu3_gpd_ring_alloc(mep);
 	if (ret < 0) {
 		mtu3_deconfig_ep(mtu, mep);
 		return ret;
 	}
+#endif
 
+#ifdef CONFIG_MTU3_QMU
 	mtu3_qmu_start(mep);
+#endif
 
 	return 0;
 }
@@ -136,12 +297,16 @@
 {
 	struct mtu3 *mtu = mep->mtu;
 
+#ifdef CONFIG_MTU3_QMU
 	mtu3_qmu_stop(mep);
+#endif
 
 	/* abort all pending requests */
 	nuke(mep, -ESHUTDOWN);
 	mtu3_deconfig_ep(mtu, mep);
+#ifdef CONFIG_MTU3_QMU
 	mtu3_gpd_ring_free(mep);
+#endif
 
 	mep->desc = NULL;
 	mep->ep.desc = NULL;
@@ -182,8 +347,7 @@
 	dev_dbg(mtu->dev, "%s %s\n", __func__, ep->name);
 
 	if (mep->flags & MTU3_EP_ENABLED) {
-		dev_WARN_ONCE(mtu->dev, true, "%s is already enabled\n",
-				mep->name);
+		dev_warn(mtu->dev, "%s is already enabled\n", mep->name);
 		return 0;
 	}
 
@@ -314,16 +478,29 @@
 
 	spin_lock_irqsave(&mtu->lock, flags);
 
+#ifdef CONFIG_MTU3_QMU
 	if (mtu3_prepare_transfer(mep)) {
 		ret = -EAGAIN;
 		goto error;
 	}
+#endif
 
 	list_add_tail(&mreq->list, &mep->req_list);
+#ifdef CONFIG_MTU3_QMU
 	mtu3_insert_gpd(mep, mreq);
 	mtu3_qmu_resume(mep);
+#else
+	if (!mep->is_in) {
+		mtu3_setbits(mtu->mac_base, U3D_EPIESR, BIT(16) << mep->epnum);
+	} else {
+		ep_write_fifo(mep, req);
+		mtu3_setbits(mtu->mac_base, U3D_EPIESR, BIT(0) << mep->epnum);
+	}
+#endif
 
+#ifdef CONFIG_MTU3_QMU
 error:
+#endif
 	spin_unlock_irqrestore(&mtu->lock, flags);
 	trace_mtu3_gadget_queue(mreq);
 
@@ -337,7 +514,7 @@
 	struct mtu3_request *r;
 	unsigned long flags;
 	int ret = 0;
-	struct mtu3 *mtu = mep->mtu;
+	struct mtu3 *mtu __attribute__((unused)) = mep->mtu;
 
 	if (!ep || !req || mreq->mep != mep)
 		return -EINVAL;
@@ -357,9 +534,13 @@
 		goto done;
 	}
 
+#ifdef CONFIG_MTU3_QMU
 	mtu3_qmu_flush(mep);  /* REVISIT: set BPS ?? */
+#endif
 	mtu3_req_complete(mep, req, -ECONNRESET);
+#ifdef CONFIG_MTU3_QMU
 	mtu3_qmu_start(mep);
+#endif
 
 done:
 	spin_unlock_irqrestore(&mtu->lock, flags);
@@ -374,7 +555,7 @@
 static int mtu3_gadget_ep_set_halt(struct usb_ep *ep, int value)
 {
 	struct mtu3_ep *mep = to_mtu3_ep(ep);
-	struct mtu3 *mtu = mep->mtu;
+	struct mtu3 *mtu __attribute__((unused)) = mep->mtu;
 	struct mtu3_request *mreq;
 	unsigned long flags;
 	int ret = 0;
@@ -467,7 +648,7 @@
 	} else {
 		mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME);
 		spin_unlock_irqrestore(&mtu->lock, flags);
-		usleep_range(10000, 11000);
+		udelay(10000);
 		spin_lock_irqsave(&mtu->lock, flags);
 		mtu3_clrbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME);
 	}
@@ -516,8 +697,7 @@
 	unsigned long flags;
 
 	if (mtu->gadget_driver) {
-		dev_err(mtu->dev, "%s is already bound to %s\n",
-			mtu->g.name, mtu->gadget_driver->driver.name);
+		dev_err(mtu->dev, "%s is already bounded\n", mtu->g.name);
 		return -EBUSY;
 	}
 
@@ -628,29 +808,16 @@
 	/* initialize maxpacket as SS */
 	if (!epnum) {
 		usb_ep_set_maxpacket_limit(&mep->ep, 512);
-		mep->ep.caps.type_control = true;
 		mep->ep.ops = &mtu3_ep0_ops;
 		mtu->g.ep0 = &mep->ep;
 	} else {
 		usb_ep_set_maxpacket_limit(&mep->ep, 1024);
-		mep->ep.caps.type_iso = true;
-		mep->ep.caps.type_bulk = true;
-		mep->ep.caps.type_int = true;
 		mep->ep.ops = &mtu3_ep_ops;
 		list_add_tail(&mep->ep.ep_list, &mtu->g.ep_list);
 	}
 
 	dev_dbg(mtu->dev, "%s, name=%s, maxp=%d\n", __func__, mep->ep.name,
 		 mep->ep.maxpacket);
-
-	if (!epnum) {
-		mep->ep.caps.dir_in = true;
-		mep->ep.caps.dir_out = true;
-	} else if (is_in) {
-		mep->ep.caps.dir_in = true;
-	} else {
-		mep->ep.caps.dir_out = true;
-	}
 }
 
 static void mtu3_gadget_init_eps(struct mtu3 *mtu)
@@ -677,14 +844,13 @@
 	mtu->g.ops = &mtu3_gadget_ops;
 	mtu->g.max_speed = mtu->max_speed;
 	mtu->g.speed = USB_SPEED_UNKNOWN;
-	mtu->g.sg_supported = 0;
 	mtu->g.name = MTU3_DRIVER_NAME;
 	mtu->is_active = 0;
 	mtu->delayed_status = false;
 
 	mtu3_gadget_init_eps(mtu);
 
-	ret = usb_add_gadget_udc(mtu->dev, &mtu->g);
+	ret = usb_add_gadget_udc((struct device *)mtu->dev, &mtu->g);
 	if (ret)
 		dev_err(mtu->dev, "failed to register udc\n");
 
diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c
index 1247c43..935745d 100644
--- a/drivers/usb/mtu3/mtu3_gadget_ep0.c
+++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c
@@ -11,31 +11,10 @@
 #include <linux/usb/composite.h>
 
 #include "mtu3.h"
-#include "mtu3_debug.h"
-#include "mtu3_trace.h"
 
 /* ep0 is always mtu3->in_eps[0] */
 #define	next_ep0_request(mtu)	next_request((mtu)->ep0)
 
-/* for high speed test mode; see USB 2.0 spec 7.1.20 */
-static const u8 mtu3_test_packet[53] = {
-	/* implicit SYNC then DATA0 to start */
-
-	/* JKJKJKJK x9 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* JJKKJJKK x8 */
-	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-	/* JJJJKKKK x8 */
-	0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
-	/* JJJJJJJKKKKKKK x8 */
-	0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	/* JJJJJJJK x8 */
-	0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd,
-	/* JKKKKKKK x10, JK */
-	0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e,
-	/* implicit CRC16 then EOP to end */
-};
-
 static char *decode_ep0_state(struct mtu3 *mtu)
 {
 	switch (mtu->ep0_state) {
@@ -117,15 +96,6 @@
 
 }
 
-static void ep0_load_test_packet(struct mtu3 *mtu)
-{
-	/*
-	 * because the length of test packet is less than max packet of HS ep0,
-	 * write it into fifo directly.
-	 */
-	ep0_write_fifo(mtu->ep0, mtu3_test_packet, sizeof(mtu3_test_packet));
-}
-
 /*
  * A. send STALL for setup transfer without data stage:
  *		set SENDSTALL and SETUPPKTRDY at the same time;
@@ -161,14 +131,14 @@
 static void ep0_set_sel_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct mtu3_request *mreq;
-	struct mtu3 *mtu;
+	struct mtu3 *mtu __attribute__((unused));
 	struct usb_set_sel_req sel;
 
 	memcpy(&sel, req->buf, sizeof(sel));
 
 	mreq = to_mtu3_request(req);
 	mtu = mreq->mtu;
-	dev_dbg(mtu->dev, "u1sel:%d, u1pel:%d, u2sel:%d, u2pel:%d\n",
+	dev_dbg(mreq->mtu->dev, "u1sel:%d, u1pel:%d, u2sel:%d, u2pel:%d\n",
 		sel.u1_sel, sel.u1_pel, sel.u2_sel, sel.u2_pel);
 }
 
@@ -262,69 +232,6 @@
 	return handled;
 }
 
-static int handle_test_mode(struct mtu3 *mtu, struct usb_ctrlrequest *setup)
-{
-	void __iomem *mbase = mtu->mac_base;
-	int handled = 1;
-	u32 value;
-
-	switch (le16_to_cpu(setup->wIndex) >> 8) {
-	case TEST_J:
-		dev_dbg(mtu->dev, "TEST_J\n");
-		mtu->test_mode_nr = TEST_J_MODE;
-		break;
-	case TEST_K:
-		dev_dbg(mtu->dev, "TEST_K\n");
-		mtu->test_mode_nr = TEST_K_MODE;
-		break;
-	case TEST_SE0_NAK:
-		dev_dbg(mtu->dev, "TEST_SE0_NAK\n");
-		mtu->test_mode_nr = TEST_SE0_NAK_MODE;
-		break;
-	case TEST_PACKET:
-		dev_dbg(mtu->dev, "TEST_PACKET\n");
-		mtu->test_mode_nr = TEST_PACKET_MODE;
-		break;
-	case OTG_SRP_REQD:
-		dev_dbg(mtu->dev, "OTG_SRP_REQD\n");
-		mtu->ssusb->otg_srp_reqd = 1;
-		break;
-	case OTG_HNP_REQD:
-		dev_dbg(mtu->dev, "OTG_HNP_REQD\n");
-		mtu->ssusb->otg_hnp_reqd = 1;
-		break;
-	default:
-		handled = -EINVAL;
-		goto out;
-	}
-
-	if (mtu->ssusb->otg_srp_reqd || mtu->ssusb->otg_hnp_reqd) {
-		mtu->ep0_state = MU3D_EP0_STATE_SETUP;
-		goto out;
-	}
-
-	mtu->test_mode = true;
-
-	/* no TX completion interrupt, and need restart platform after test */
-	if (mtu->test_mode_nr == TEST_PACKET_MODE)
-		ep0_load_test_packet(mtu);
-
-	/* send status before entering test mode. */
-	value = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS;
-	mtu3_writel(mbase, U3D_EP0CSR, value | EP0_SETUPPKTRDY | EP0_DATAEND);
-
-	/* wait for ACK status sent by host */
-	readl_poll_timeout_atomic(mbase + U3D_EP0CSR, value,
-			!(value & EP0_DATAEND), 100, 5000);
-
-	mtu3_writel(mbase, U3D_USB2_TEST_MODE, mtu->test_mode_nr);
-
-	mtu->ep0_state = MU3D_EP0_STATE_SETUP;
-
-out:
-	return handled;
-}
-
 static int ep0_handle_feature_dev(struct mtu3 *mtu,
 		struct usb_ctrlrequest *setup, bool set)
 {
@@ -337,13 +244,6 @@
 		mtu->may_wakeup = !!set;
 		handled = 1;
 		break;
-	case USB_DEVICE_TEST_MODE:
-		if (!set || (mtu->g.speed != USB_SPEED_HIGH) ||
-			(le16_to_cpu(setup->wIndex) & 0xff))
-			break;
-
-		handled = handle_test_mode(mtu, setup);
-		break;
 	case USB_DEVICE_U1_ENABLE:
 		if (mtu->g.speed < USB_SPEED_SUPER ||
 		    mtu->g.state != USB_STATE_CONFIGURED)
@@ -704,6 +604,9 @@
 	u32 len;
 
 	int_status = mtu3_readl(mbase, U3D_EPISR);
+#ifndef CONFIG_MTU3_QMU
+	int_status &= (EP0ISR | SETUPENDISR);
+#endif
 	int_status &= mtu3_readl(mbase, U3D_EPIER);
 	mtu3_writel(mbase, U3D_EPISR, int_status); /* W1C */
 
@@ -842,7 +745,7 @@
 {
 	struct mtu3_ep *mep;
 	struct mtu3_request *mreq;
-	struct mtu3 *mtu;
+	struct mtu3 *mtu __attribute__((unused));
 	unsigned long flags;
 	int ret = 0;
 
diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h
index 8382d06..d157c4d 100644
--- a/drivers/usb/mtu3/mtu3_hw_regs.h
+++ b/drivers/usb/mtu3/mtu3_hw_regs.h
@@ -42,6 +42,7 @@
 #define U3D_RX1CSR0		(SSUSB_DEV_BASE + 0x0210)
 #define U3D_RX1CSR1		(SSUSB_DEV_BASE + 0x0214)
 #define U3D_RX1CSR2		(SSUSB_DEV_BASE + 0x0218)
+#define U3D_RX1CSR3		(SSUSB_DEV_BASE + 0x021C)
 
 #define U3D_FIFO0		(SSUSB_DEV_BASE + 0x0300)
 
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 1f4b739..b7cafa9 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -5,18 +5,21 @@
  * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
  */
 
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
+#include <asm/io.h>
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/of_access.h>
+#include <generic-phy.h>
+#include <power/regulator.h>
+
 #include <linux/iopoll.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
 
 #include "mtu3.h"
 #include "mtu3_dr.h"
-#include "mtu3_debug.h"
+
 
 /* u2-port0 should be powered on and enabled; */
 int ssusb_check_clocks(struct ssusb_mtk *ssusb, u32 ex_clks)
@@ -29,14 +32,12 @@
 			SSUSB_REF_RST_B_STS;
 
 	ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS1, value,
-			(check_val == (value & check_val)), 100, 20000);
-	if (ret) {
+			(check_val == (value & check_val)), 20000);
+	if (ret)
 		dev_err(ssusb->dev, "clks of sts1 are not stable!\n");
-		return ret;
-	}
 
 	ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS2, value,
-			(value & SSUSB_U2_MAC_SYS_RST_B_STS), 100, 10000);
+			(value & SSUSB_U2_MAC_SYS_RST_B_STS), 10000);
 	if (ret) {
 		dev_err(ssusb->dev, "mac2 clock is not stable\n");
 		return ret;
@@ -72,7 +73,7 @@
 	int ret;
 
 	for (i = 0; i < ssusb->num_phys; i++) {
-		ret = phy_init(ssusb->phys[i]);
+		ret = generic_phy_init(ssusb->phys[i]);
 		if (ret)
 			goto exit_phy;
 	}
@@ -80,7 +81,7 @@
 
 exit_phy:
 	for (; i > 0; i--)
-		phy_exit(ssusb->phys[i - 1]);
+		generic_phy_exit(ssusb->phys[i - 1]);
 
 	return ret;
 }
@@ -90,7 +91,7 @@
 	int i;
 
 	for (i = 0; i < ssusb->num_phys; i++)
-		phy_exit(ssusb->phys[i]);
+		generic_phy_exit(ssusb->phys[i]);
 
 	return 0;
 }
@@ -101,7 +102,7 @@
 	int ret;
 
 	for (i = 0; i < ssusb->num_phys; i++) {
-		ret = phy_power_on(ssusb->phys[i]);
+		ret = generic_phy_power_on(ssusb->phys[i]);
 		if (ret)
 			goto power_off_phy;
 	}
@@ -109,7 +110,7 @@
 
 power_off_phy:
 	for (; i > 0; i--)
-		phy_power_off(ssusb->phys[i - 1]);
+		generic_phy_power_off(ssusb->phys[i - 1]);
 
 	return ret;
 }
@@ -119,7 +120,7 @@
 	unsigned int i;
 
 	for (i = 0; i < ssusb->num_phys; i++)
-		phy_power_off(ssusb->phys[i]);
+		generic_phy_power_off(ssusb->phys[i]);
 }
 
 static int ssusb_clks_enable(struct ssusb_mtk *ssusb)
@@ -174,12 +175,6 @@
 {
 	int ret = 0;
 
-	ret = regulator_enable(ssusb->vusb33);
-	if (ret) {
-		dev_err(ssusb->dev, "failed to enable vusb33\n");
-		goto vusb33_err;
-	}
-
 	ret = ssusb_clks_enable(ssusb);
 	if (ret)
 		goto clks_err;
@@ -203,15 +198,12 @@
 phy_init_err:
 	ssusb_clks_disable(ssusb);
 clks_err:
-	regulator_disable(ssusb->vusb33);
-vusb33_err:
 	return ret;
 }
 
 static void ssusb_rscs_exit(struct ssusb_mtk *ssusb)
 {
 	ssusb_clks_disable(ssusb);
-	regulator_disable(ssusb->vusb33);
 	ssusb_phy_power_off(ssusb);
 	ssusb_phy_exit(ssusb);
 }
@@ -233,7 +225,7 @@
 }
 
 /* ignore the error if the clock does not exist */
-static struct clk *get_optional_clk(struct device *dev, const char *id)
+static struct clk *get_optional_clk(struct udevice *dev, const char *id)
 {
 	struct clk *opt_clk;
 
@@ -245,22 +237,14 @@
 	return opt_clk;
 }
 
-static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
+static int get_ssusb_rscs(struct udevice *dev, struct ssusb_mtk *ssusb)
 {
-	struct device_node *node = pdev->dev.of_node;
+	const struct device_node *node = ofnode_to_np(dev->node);
 	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
-	struct device *dev = &pdev->dev;
-	struct regulator *vbus;
-	struct resource *res;
+	struct resource res;
 	int i;
 	int ret;
 
-	ssusb->vusb33 = devm_regulator_get(dev, "vusb33");
-	if (IS_ERR(ssusb->vusb33)) {
-		dev_err(dev, "failed to get vusb33\n");
-		return PTR_ERR(ssusb->vusb33);
-	}
-
 	ssusb->sys_clk = devm_clk_get(dev, "sys_ck");
 	if (IS_ERR(ssusb->sys_clk)) {
 		dev_err(dev, "failed to get sys clock\n");
@@ -291,65 +275,42 @@
 	}
 
 	for (i = 0; i < ssusb->num_phys; i++) {
-		ssusb->phys[i] = devm_of_phy_get_by_index(dev, node, i);
-		if (IS_ERR(ssusb->phys[i])) {
+		ssusb->phys[i] = devm_kzalloc(dev, sizeof(struct phy), GFP_KERNEL);
+		ret = generic_phy_get_by_index(dev, i, ssusb->phys[i]);
+		if (ret) {
 			dev_err(dev, "failed to get phy-%d\n", i);
-			return PTR_ERR(ssusb->phys[i]);
+			return ret;
 		}
 	}
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc");
-	ssusb->ippc_base = devm_ioremap_resource(dev, res);
+	dev_read_resource_byname(dev, "ippc", &res);
+	ssusb->ippc_base = devm_ioremap(dev, res.start, resource_size(&res));
 	if (IS_ERR(ssusb->ippc_base))
 		return PTR_ERR(ssusb->ippc_base);
 
-        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac");
-        ssusb->mac_base = devm_ioremap_resource(dev, res);
+	dev_read_resource_byname(dev, "mac", &res);
+        ssusb->mac_base = devm_ioremap(dev, res.start, resource_size(&res));
         if (IS_ERR(ssusb->mac_base))
                 return PTR_ERR(ssusb->mac_base);
 
-	ssusb->force_vbus = of_property_read_bool(node, "mediatek,force-vbus");
+	ssusb->force_vbus = ofnode_read_bool(dev->node, "mediatek,force-vbus");
 
-	ssusb->dr_mode = usb_get_dr_mode(dev);
-	if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN)
-		ssusb->dr_mode = USB_DR_MODE_OTG;
-
+	/* FIXME: usb_get_dr_mode doesn't work, assume peripheral */
+	ssusb->dr_mode = USB_DR_MODE_PERIPHERAL;
 	if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL)
 		return 0;
 
-	/* if host role is supported */
-	ret = ssusb_wakeup_of_property_parse(ssusb, node);
-	if (ret) {
-		dev_err(dev, "failed to parse uwk property\n");
-		return ret;
-	}
-
 	/* optional property, ignore the error if it does not exist */
-	of_property_read_u32(node, "mediatek,u3p-dis-msk",
-			     &ssusb->u3p_dis_msk);
-
-	vbus = devm_regulator_get(&pdev->dev, "vbus");
-	if (IS_ERR(vbus)) {
-		dev_err(dev, "failed to get vbus\n");
-		return PTR_ERR(vbus);
-	}
-	otg_sx->vbus = vbus;
+	ofnode_read_u32(dev->node, "mediatek,u3p-dis-msk",
+			(u32 *)&ssusb->u3p_dis_msk);
 
 	if (ssusb->dr_mode == USB_DR_MODE_HOST)
 		return 0;
 
 	/* if dual-role mode is supported */
-	otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
+	otg_sx->is_u3_drd = ofnode_read_bool(dev->node, "mediatek,usb3-drd");
 	otg_sx->manual_drd_enabled =
-		of_property_read_bool(node, "enable-manual-drd");
-
-	if (of_property_read_bool(node, "extcon")) {
-		otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
-		if (IS_ERR(otg_sx->edev)) {
-			dev_err(ssusb->dev, "couldn't get extcon device\n");
-			return PTR_ERR(otg_sx->edev);
-		}
-	}
+		ofnode_read_bool(dev->node, "enable-manual-drd");
 
 	dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk: %x, drd: %s\n",
 		ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk,
@@ -358,44 +319,25 @@
 	return 0;
 }
 
-static int mtu3_probe(struct platform_device *pdev)
+static int mtu3_probe(struct udevice *udev)
 {
-	struct device_node *node = pdev->dev.of_node;
-	struct device *dev = &pdev->dev;
 	struct ssusb_mtk *ssusb;
 	int ret = -ENOMEM;
 
 	/* all elements are set to ZERO as default value */
-	ssusb = devm_kzalloc(dev, sizeof(*ssusb), GFP_KERNEL);
+	ssusb = dev_get_platdata(udev);
 	if (!ssusb)
 		return -ENOMEM;
+	ssusb->dev = udev;
 
-	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-	if (ret) {
-		dev_err(dev, "No suitable DMA config available\n");
-		return -ENOTSUPP;
-	}
-
-	platform_set_drvdata(pdev, ssusb);
-	ssusb->dev = dev;
-
-	ret = get_ssusb_rscs(pdev, ssusb);
+	ret = get_ssusb_rscs(udev, ssusb);
 	if (ret)
 		return ret;
 
-	ssusb_debugfs_create_root(ssusb);
-
-	/* enable power domain */
-	pm_runtime_enable(dev);
-	pm_runtime_get_sync(dev);
-	device_enable_async_suspend(dev);
-
 	ret = ssusb_rscs_init(ssusb);
 	if (ret)
 		goto comm_init_err;
-
 	ssusb_ip_sw_reset(ssusb);
-
 	if (IS_ENABLED(CONFIG_USB_MTU3_HOST))
 		ssusb->dr_mode = USB_DR_MODE_HOST;
 	else if (IS_ENABLED(CONFIG_USB_MTU3_GADGET))
@@ -403,7 +345,6 @@
 
 	/* default as host */
 	ssusb->is_host = !(ssusb->dr_mode == USB_DR_MODE_PERIPHERAL);
-
 	switch (ssusb->dr_mode) {
 	case USB_DR_MODE_PERIPHERAL:
 		ret = ssusb_gadget_init(ssusb);
@@ -412,28 +353,6 @@
 			goto comm_exit;
 		}
 		break;
-	case USB_DR_MODE_HOST:
-		ret = ssusb_host_init(ssusb, node);
-		if (ret) {
-			dev_err(dev, "failed to initialize host\n");
-			goto comm_exit;
-		}
-		break;
-	case USB_DR_MODE_OTG:
-		ret = ssusb_gadget_init(ssusb);
-		if (ret) {
-			dev_err(dev, "failed to initialize gadget\n");
-			goto comm_exit;
-		}
-
-		ret = ssusb_host_init(ssusb, node);
-		if (ret) {
-			dev_err(dev, "failed to initialize host\n");
-			goto gadget_exit;
-		}
-
-		ssusb_otg_switch_init(ssusb);
-		break;
 	default:
 		dev_err(dev, "unsupported mode: %d\n", ssusb->dr_mode);
 		ret = -EINVAL;
@@ -442,126 +361,40 @@
 
 	return 0;
 
-gadget_exit:
-	ssusb_gadget_exit(ssusb);
 comm_exit:
 	ssusb_rscs_exit(ssusb);
 comm_init_err:
-	pm_runtime_put_sync(dev);
-	pm_runtime_disable(dev);
-	ssusb_debugfs_remove_root(ssusb);
 
 	return ret;
 }
 
-static int mtu3_remove(struct platform_device *pdev)
+static int mtu3_remove(struct udevice *udev)
 {
-	struct ssusb_mtk *ssusb = platform_get_drvdata(pdev);
+	struct ssusb_mtk *ssusb = dev_get_platdata(udev);
 
 	switch (ssusb->dr_mode) {
 	case USB_DR_MODE_PERIPHERAL:
 		ssusb_gadget_exit(ssusb);
 		break;
-	case USB_DR_MODE_HOST:
-		ssusb_host_exit(ssusb);
-		break;
-	case USB_DR_MODE_OTG:
-		ssusb_otg_switch_exit(ssusb);
-		ssusb_gadget_exit(ssusb);
-		ssusb_host_exit(ssusb);
-		break;
 	default:
 		return -EINVAL;
 	}
 
 	ssusb_rscs_exit(ssusb);
-	pm_runtime_put_sync(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
-	ssusb_debugfs_remove_root(ssusb);
 
 	return 0;
 }
 
-/*
- * when support dual-role mode, we reject suspend when
- * it works as device mode;
- */
-static int __maybe_unused mtu3_suspend(struct device *dev)
-{
-	struct ssusb_mtk *ssusb = dev_get_drvdata(dev);
-
-	dev_dbg(dev, "%s\n", __func__);
-
-	/* REVISIT: disconnect it for only device mode? */
-	if (!ssusb->is_host)
-		return 0;
-
-	ssusb_host_disable(ssusb, true);
-	ssusb_phy_power_off(ssusb);
-	ssusb_clks_disable(ssusb);
-	ssusb_wakeup_set(ssusb, true);
-
-	return 0;
-}
-
-static int __maybe_unused mtu3_resume(struct device *dev)
-{
-	struct ssusb_mtk *ssusb = dev_get_drvdata(dev);
-	int ret;
-
-	dev_dbg(dev, "%s\n", __func__);
-
-	if (!ssusb->is_host)
-		return 0;
-
-	ssusb_wakeup_set(ssusb, false);
-	ret = ssusb_clks_enable(ssusb);
-	if (ret)
-		goto clks_err;
-
-	ret = ssusb_phy_power_on(ssusb);
-	if (ret)
-		goto phy_err;
-
-	ssusb_host_enable(ssusb);
-
-	return 0;
-
-phy_err:
-	ssusb_clks_disable(ssusb);
-clks_err:
-	return ret;
-}
-
-static const struct dev_pm_ops mtu3_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mtu3_suspend, mtu3_resume)
+static const struct udevice_id mtk_mtu3_ids[] = {
+        { .compatible = "mediatek,mt8183-mtu3" },
+        { }
 };
 
-#define DEV_PM_OPS (IS_ENABLED(CONFIG_PM) ? &mtu3_pm_ops : NULL)
-
-#ifdef CONFIG_OF
-
-static const struct of_device_id mtu3_of_match[] = {
-	{.compatible = "mediatek,mt8173-mtu3",},
-	{.compatible = "mediatek,mtu3",},
-	{},
+U_BOOT_DRIVER(mtk_musb) = {
+        .name     = "mtu3",
+        .id       = UCLASS_USB_GADGET_GENERIC,
+        .of_match = mtk_mtu3_ids,
+        .probe    = mtu3_probe,
+        .remove   = mtu3_remove,
+        .platdata_auto_alloc_size = sizeof(struct ssusb_mtk),
 };
-
-MODULE_DEVICE_TABLE(of, mtu3_of_match);
-
-#endif
-
-static struct platform_driver mtu3_driver = {
-	.probe = mtu3_probe,
-	.remove = mtu3_remove,
-	.driver = {
-		.name = MTU3_DRIVER_NAME,
-		.pm = DEV_PM_OPS,
-		.of_match_table = of_match_ptr(mtu3_of_match),
-	},
-};
-module_platform_driver(mtu3_driver);
-
-MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MediaTek USB3 DRD Controller Driver");
diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c
index 494e5ae..5a318d8 100644
--- a/drivers/usb/mtu3/mtu3_qmu.c
+++ b/drivers/usb/mtu3/mtu3_qmu.c
@@ -18,11 +18,11 @@
  * For more detailed information, please refer to QMU Programming Guide
  */
 
-#include <linux/dmapool.h>
+#include <dm.h>
+#include <dma.h>
 #include <linux/iopoll.h>
 
 #include "mtu3.h"
-#include "mtu3_trace.h"
 
 #define QMU_CHECKSUM_LEN	16
 
@@ -168,7 +168,8 @@
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 
 	/* software own all gpds as default */
-	gpd = dma_pool_zalloc(mep->mtu->qmu_gpd_pool, GFP_ATOMIC, &ring->dma);
+	gpd = memalign(QMU_GPD_SIZE, QMU_GPD_RING_SIZE);
+	ring->dma = (dma_addr_t)gpd;
 	if (gpd == NULL)
 		return -ENOMEM;
 
@@ -181,8 +182,7 @@
 {
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 
-	dma_pool_free(mep->mtu->qmu_gpd_pool,
-			ring->start, ring->dma);
+	free(ring->start);
 	memset(ring, 0, sizeof(*ring));
 }
 
@@ -309,6 +309,7 @@
 	gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO);
 
 	mreq->gpd = gpd;
+
 	trace_mtu3_prepare_gpd(mep, gpd);
 
 	return 0;
@@ -384,8 +385,8 @@
 	}
 	mtu3_writel(mbase, qcsr, QMU_Q_STOP);
 
-	ret = readl_poll_timeout_atomic(mbase + qcsr, value,
-			!(value & QMU_Q_ACTIVE), 1, 1000);
+	ret = readl_poll_timeout(mbase + qcsr, value,
+			!(value & QMU_Q_ACTIVE), 1000);
 	if (ret) {
 		dev_err(mtu->dev, "stop %s's qmu failed\n", mep->name);
 		return;
@@ -441,8 +442,8 @@
 
 	mtu3_clrbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN);
 
-	ret = readl_poll_timeout_atomic(mbase + MU3D_EP_TXCR0(mep->epnum),
-			txcsr, !(txcsr & TX_FIFOFULL), 1, 1000);
+	ret = readl_poll_timeout(mbase + MU3D_EP_TXCR0(mep->epnum),
+			txcsr, !(txcsr & TX_FIFOFULL), 1000);
 	if (ret) {
 		dev_err(mtu->dev, "%s wait for fifo empty fail\n", __func__);
 		return;
@@ -623,19 +624,9 @@
 
 int mtu3_qmu_init(struct mtu3 *mtu)
 {
-
-	compiletime_assert(QMU_GPD_SIZE == 16, "QMU_GPD size SHOULD be 16B");
-
-	mtu->qmu_gpd_pool = dma_pool_create("QMU_GPD", mtu->dev,
-			QMU_GPD_RING_SIZE, QMU_GPD_SIZE, 0);
-
-	if (!mtu->qmu_gpd_pool)
-		return -ENOMEM;
-
 	return 0;
 }
 
 void mtu3_qmu_exit(struct mtu3 *mtu)
 {
-	dma_pool_destroy(mtu->qmu_gpd_pool);
 }