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);
}