[PATCH 2/4] arm: dts: mt2701: Add usb2 device nodes

2018-12-26 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 34 ++
 2 files changed, 55 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index be0edb3..2635911 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -60,6 +61,20 @@
>;
default-brightness-level = <9>;
};
+
+   extcon_usb: extcon_iddig {
+   compatible = "linux,extcon-usb-gpio";
+   id-gpio = <&pio 44 GPIO_ACTIVE_HIGH>;
+   };
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -229,3 +244,9 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 180377e..495ece9 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -670,6 +670,40 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+   "mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   phy-names = "usb2-phy";
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH 1/4] dt-bindings: usb: musb: Add support for MediaTek musb controller

2018-12-26 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode

Signed-off-by: Min Guo 
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 49 ++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..e899c9b
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,49 @@
+MediaTek musb DRC/OTG controller
+---
+
+Required properties:
+ - compatible  : should be "mediatek,-musb",
+   "mediatek,mtk-musb", soc-model is the name of SoC, such as
+   mt2701, when using "mediatek,mtk-musb" compatible string, you
+   need SoC specific ones in addition, one of:
+   - "mediatek,mt2701-musb"
+ - reg : specifies physical base address and size of
+   the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - phy-names   : should be "usb2-phy"
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+   refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+   each entry in clock-names
+ - clock-names : must contain "main","mcu","univpll"
+   for clocks of controller
+
+Optional properties:
+ - extcon : external connector for VBUS and IDPIN changes detection,
+   needed when supports dual-role mode.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+   dual-role mode.
+ - power-domains   : a phandle to USB power domain node to control USB's
+   MTCMOS
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb";
+   "mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   phy-names = "usb2-phy";
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+};
-- 
1.9.1



[PATCH 3/4] usb: musb: Move musbhsdma macro definition to musb_dma.h

2018-12-26 Thread min.guo
From: Min Guo 

Because the MediaTek musb controller dose not have a
separate DMA interrupt, these macros are required to
access the dma registers

Signed-off-by: Min Guo 
---
 drivers/usb/musb/musb_dma.h  | 6 ++
 drivers/usb/musb/musbhsdma.c | 7 +--
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 8f60271..281e75d3 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -35,6 +35,12 @@
  *whether shared with the Inventra core or separate.
  */
 
+#define MUSB_HSDMA_BASE0x200
+#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL 0x4
+#define MUSB_HSDMA_ADDRESS 0x8
+#define MUSB_HSDMA_COUNT   0xc
+
 #defineDMA_ADDR_INVALID(~(dma_addr_t)0)
 
 #ifdef CONFIG_MUSB_PIO_ONLY
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index a688f7f..824adcb 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -10,12 +10,7 @@
 #include 
 #include 
 #include "musb_core.h"
-
-#define MUSB_HSDMA_BASE0x200
-#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL 0x4
-#define MUSB_HSDMA_ADDRESS 0x8
-#define MUSB_HSDMA_COUNT   0xc
+#include "musb_dma.h"
 
 #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)  \
(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
-- 
1.9.1



[PATCH 0/4] Add MediaTek MUSB Controller Driver

2018-12-26 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders

Min Guo (4):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Move musbhsdma macro definition to musb_dma.h
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  49 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  34 ++
 drivers/usb/musb/Kconfig   |   8 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 562 +
 drivers/usb/musb/musb_core.c   |  10 +
 drivers/usb/musb/musb_core.h   |   1 +
 drivers/usb/musb/musb_dma.h|   7 +
 drivers/usb/musb/musb_host.c   |  79 ++-
 drivers/usb/musb/musb_regs.h   |   6 +
 drivers/usb/musb/musbhsdma.c   |  41 +-
 12 files changed, 782 insertions(+), 37 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH 4/4] usb: musb: Add support for MediaTek musb controller

2018-12-26 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
 drivers/usb/musb/Kconfig |   8 +-
 drivers/usb/musb/Makefile|   1 +
 drivers/usb/musb/mediatek.c  | 562 +++
 drivers/usb/musb/musb_core.c |  10 +
 drivers/usb/musb/musb_core.h |   1 +
 drivers/usb/musb/musb_dma.h  |   1 +
 drivers/usb/musb/musb_host.c |  79 --
 drivers/usb/musb/musb_regs.h |   6 +
 drivers/usb/musb/musbhsdma.c |  34 ++-
 9 files changed, 671 insertions(+), 31 deletions(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index ad08895..540fc9f 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -115,6 +115,12 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -141,7 +147,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..15a6460
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,562 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+enum mtk_vbus_id_state {
+   MTK_ID_FLOAT = 1,
+   MTK_ID_GROUND,
+   MTK_VBUS_OFF,
+   MTK_VBUS_VALID,
+};
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   struct regulator *vbus;
+   struct extcon_dev *edev;
+   struct notifier_block vbus_nb;
+   struct notifier_block id_nb;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+   return PTR_ERR(glue->univpll);
+   }
+
+   return 0;
+}
+
+static int mtk_musb_clks_enable(struct mtk_glue *glue)
+{
+   int ret;
+
+   ret = clk_prepare_enable(glue->main);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable main clock\n");
+   goto err_main_clk;
+   }
+
+   ret = clk_prepare_enable(glue->mcu);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable mcu clock\n");
+   goto err_mcu_clk;
+   }
+
+   ret = clk_prepare_enable(glue->univpll);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable univpll clock\n");
+   goto err_univpll_clk;
+   }
+
+   return 0;
+
+err_univpll_clk:
+   clk_disable_unprepare(glue->mcu);
+err_mcu_clk:
+   clk_disable_unprepare(glue->main);
+err_main_clk:
+   return ret;
+}
+
+static void mtk_musb_clks_disable(struct mtk_glue *glue)
+{
+   clk_disable_unprepare(glue->univpll);
+   clk_disable_unprepare(glue->m

[PATCH v2] usb: musb: remove unused variable 'devctl'

2020-11-23 Thread min.guo
From: Min Guo 

Remove unused 'devctl' variable to fix compile warnings:

drivers/usb/musb/musbhsdma.c: In function 'dma_controller_irq':
drivers/usb/musb/musbhsdma.c:324:8: warning: variable 'devctl' set
but not used [-Wunused-but-set-variable]

Signed-off-by: Min Guo 
---
changes in v2
suggested by Alan Stern:
Add void before musb_read to indicate that the register MUSB_DEVCTL
was intended to be read and discarded.
---
 drivers/usb/musb/musbhsdma.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 0aacfc8be5a1..f59a009c533e 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -321,8 +321,6 @@ irqreturn_t dma_controller_irq(int irq, void *private_data)
musb_channel->channel.status =
MUSB_DMA_STATUS_BUS_ABORT;
} else {
-   u8 devctl;
-
addr = musb_read_hsdma_addr(mbase,
bchannel);
channel->actual_len = addr
@@ -336,7 +334,7 @@ irqreturn_t dma_controller_irq(int irq, void *private_data)
< musb_channel->len) ?
"=> reconfig 0" : "=> complete");
 
-   devctl = musb_readb(mbase, MUSB_DEVCTL);
+   (void)musb_readb(mbase, MUSB_DEVCTL);
 
channel->status = MUSB_DMA_STATUS_FREE;
 
-- 
2.18.0



[PATCH v3] usb: musb: remove unused variable 'devctl'

2020-11-24 Thread min.guo
From: Min Guo 

Remove unused 'devctl' variable to fix compile warnings:

drivers/usb/musb/musbhsdma.c: In function 'dma_controller_irq':
drivers/usb/musb/musbhsdma.c:324:8: warning: variable 'devctl' set
but not used [-Wunused-but-set-variable]

Signed-off-by: Min Guo 
---
changes in v3
suggested by Greg Kroah-Hartman:
Add a comment.

changes in v2
suggested by Alan Stern:
Add void before musb_read to indicate that the register MUSB_DEVCTL
was intended to be read and discarded.
---
 drivers/usb/musb/musbhsdma.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 0aacfc8be5a1..2a345b4ad015 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -321,8 +321,6 @@ irqreturn_t dma_controller_irq(int irq, void *private_data)
musb_channel->channel.status =
MUSB_DMA_STATUS_BUS_ABORT;
} else {
-   u8 devctl;
-
addr = musb_read_hsdma_addr(mbase,
bchannel);
channel->actual_len = addr
@@ -336,7 +334,11 @@ irqreturn_t dma_controller_irq(int irq, void *private_data)
< musb_channel->len) ?
"=> reconfig 0" : "=> complete");
 
-   devctl = musb_readb(mbase, MUSB_DEVCTL);
+   /*
+* Some hardware may need to read the
+* MUSB_DEVCTL register once to take effect.
+*/
+   (void)musb_readb(mbase, MUSB_DEVCTL);
 
channel->status = MUSB_DMA_STATUS_FREE;
 
-- 
2.18.0



[PATCH v7 0/6] Add MediaTek MUSB Controller Driver

2019-08-30 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v7:
changes of dt-bindings and DTS:
1. Change compatible string
2. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
changes of dt-bindings:
1. Modify usb connector child node
changes of DTS:
1. Modify usb connector child node
changes of driver:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode,
   depends on [1]
3. Remove set vbus function

[1] [v6,09/10] usb: roles: add USB Type-B GPIO connector driver
https://patchwork.kernel.org/patch/10966361/

changes in v5:
changes of dt-bindings suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node
changes of DTS:
1. Add usb connector child node
changes of driver suggested by Bin:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts
2. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
3. Make musb_clearb/w() return the value of musb_readb/w()

changes in v4:
changes of dt-bindings suggested by Sergei:
1. String alignment
changes of driver suggested by Tony and Bin:
1. Add a new patch for set/get_toggle()
2. Add a new patch for noirq type of dma
3. Add a new patch musb_clearb/w()
4. Abondon patch "usb: musb: Delete the const attribute of addr parameter in 
readb/w/l hooks"

changes in v3:
changes of driver suggested by Bin:
1. Add a new patch for musb_readb/w/l() to remove const attribute 
2. Use is_out as function parameter in set_toggle/get_toggle() hooks
3. Remove 'u8/u16 data' parameter in clearb/w() hooks
4. Remove musb_default_clearb/w()
5. Replace musb_readb/w() with musb_clearb/w() to clear pending interrupts 
6. Add comments to clearb/w() hooks
7. Replace musb_save_toggle() with musb->io.get_toggle()
8. Replace musb_set_toggle() with musb->io.set_toggle()

changes in v2:
changes of dt-bindings suggested by Rob and Bin:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (6):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Add get/set toggle hooks
  usb: musb: Add noirq type of dma create interface
  usb: musb: Add musb_clearb/w() interface
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  55 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   9 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 582 +
 drivers/usb/musb/musb_core.c   |  74 ++-
 drivers/usb/musb/musb_core.h   |  13 +-
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  46 +-
 drivers/usb/musb/musb_io.h |  12 +-
 drivers/usb/musb/musbhsdma.c   |  56 +-
 drivers/usb/musb/sunxi.c   |   4 +-
 drivers/usb/musb/tusb6010.c|   2 +-
 14 files changed, 845 insertions(+), 72 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH v7 1/6] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-08-30 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
---
changes in v7:
1. Modify compatible as
- compatible : should be one of:
   "mediatek,mt2701-musb"
   ...
   followed by "mediatek,mtk-musb"
2. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
1. Modify usb connector child node

changes in v5:
suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node

changes in v4:
suggested by Sergei:
1. String alignment

changes in v3:
1. no changes

changes in v2:
suggested by Bin:
1. Modify DRC to DRD
suggested by Rob:
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 55 ++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..2cb9e91
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,55 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be one of:
+ "mediatek,mt2701-musb"
+ ...
+ followed by "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+ the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+ refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+ each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+ for clocks of controller
+
+Optional properties:
+ - power-domains   : a phandle to USB power domain node to control USB's
+ MTCMOS
+
+Required child nodes:
+ usb connector node as defined in bindings/connector/usb-connector.txt
+Optional properties:
+ - id-gpios: input GPIO for USB ID pin.
+ - vbus-gpios  : input GPIO for USB VBUS pin.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+ dual-role mode
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   connector{
+   compatible = "gpio-usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
-- 
1.9.1



[PATCH v7 4/6] usb: musb: Add noirq type of dma create interface

2019-08-30 Thread min.guo
From: Min Guo 

Add noirq type of dma create interface for platform which do not
have dedicated DMA interrupt line, move musbhsdma macro definition
to musb_dma.h

Signed-off-by: Min Guo 
---
changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_dma.h  |  9 
 drivers/usb/musb/musbhsdma.c | 54 ++--
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 8f60271..05103ea 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -35,6 +35,12 @@
  *whether shared with the Inventra core or separate.
  */
 
+#define MUSB_HSDMA_BASE0x200
+#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL 0x4
+#define MUSB_HSDMA_ADDRESS 0x8
+#define MUSB_HSDMA_COUNT   0xc
+
 #defineDMA_ADDR_INVALID(~(dma_addr_t)0)
 
 #ifdef CONFIG_MUSB_PIO_ONLY
@@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct 
dma_controller *d) { }
 extern struct dma_controller *
 musbhs_dma_controller_create(struct musb *musb, void __iomem *base);
 extern void musbhs_dma_controller_destroy(struct dma_controller *c);
+extern struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base);
+extern irqreturn_t dma_controller_irq(int irq, void *private_data);
 
 extern struct dma_controller *
 tusb_dma_controller_create(struct musb *musb, void __iomem *base);
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 5fc6825..d549c0b 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -10,12 +10,7 @@
 #include 
 #include 
 #include "musb_core.h"
-
-#define MUSB_HSDMA_BASE0x200
-#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL 0x4
-#define MUSB_HSDMA_ADDRESS 0x8
-#define MUSB_HSDMA_COUNT   0xc
+#include "musb_dma.h"
 
 #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)  \
(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
@@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel)
return 0;
 }
 
-static irqreturn_t dma_controller_irq(int irq, void *private_data)
+irqreturn_t dma_controller_irq(int irq, void *private_data)
 {
struct musb_dma_controller *controller = private_data;
struct musb *musb = controller->private_data;
@@ -383,6 +378,7 @@ static irqreturn_t dma_controller_irq(int irq, void 
*private_data)
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
 }
+EXPORT_SYMBOL_GPL(dma_controller_irq);
 
 void musbhs_dma_controller_destroy(struct dma_controller *c)
 {
@@ -398,18 +394,10 @@ void musbhs_dma_controller_destroy(struct dma_controller 
*c)
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy);
 
-struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
-   void __iomem *base)
+static struct musb_dma_controller *
+dma_controller_alloc(struct musb *musb, void __iomem *base)
 {
struct musb_dma_controller *controller;
-   struct device *dev = musb->controller;
-   struct platform_device *pdev = to_platform_device(dev);
-   int irq = platform_get_irq_byname(pdev, "dma");
-
-   if (irq <= 0) {
-   dev_err(dev, "No DMA interrupt line!\n");
-   return NULL;
-   }
 
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
@@ -423,6 +411,25 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
controller->controller.channel_release = dma_channel_release;
controller->controller.channel_program = dma_channel_program;
controller->controller.channel_abort = dma_channel_abort;
+   return controller;
+}
+
+struct dma_controller *
+musbhs_dma_controller_create(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+   struct device *dev = musb->controller;
+   struct platform_device *pdev = to_platform_device(dev);
+   int irq = platform_get_irq_byname(pdev, "dma");
+
+   if (irq <= 0) {
+   dev_err(dev, "No DMA interrupt line!\n");
+   return NULL;
+   }
+
+   controller = dma_controller_alloc(musb, base);
+   if (!controller)
+   return NULL;
 
if (request_irq(irq, dma_controller_irq, 0,
dev_name(musb->controller), &controller->controller)) {
@@ -437,3 +444,16 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
return &controller->controller;
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_create);
+
+struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base)
+{
+   st

[PATCH v7 3/6] usb: musb: Add get/set toggle hooks

2019-08-30 Thread min.guo
From: Min Guo 

Add get/set toggle hooks in struct musb_io and struct musb_platform_ops
for special platform; remove function musb_save_toggle, use the set/get
callback to handle toggle.

Signed-off-by: Min Guo 
---
changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 42 
 drivers/usb/musb/musb_core.h |  5 +
 drivers/usb/musb/musb_host.c | 46 ++--
 drivers/usb/musb/musb_io.h   |  4 
 4 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 9f5a481..491d361 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -274,6 +274,38 @@ static void musb_default_writew(void __iomem *addr, 
unsigned offset, u16 data)
__raw_writew(data, addr + offset);
 }
 
+static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out)
+{
+   void __iomem *epio = qh->hw_ep->regs;
+   u16 csr;
+
+   if (is_out)
+   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+   else
+   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+
+   return csr;
+}
+
+static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out,
+  struct urb *urb)
+{
+   u16 csr;
+   u16 toggle;
+
+   toggle = usb_gettoggle(urb->dev, qh->epnum, is_out);
+
+   if (is_out)
+   csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
+   | MUSB_TXCSR_H_DATATOGGLE)
+   : MUSB_TXCSR_CLRDATATOG;
+   else
+   csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
+   | MUSB_RXCSR_H_DATATOGGLE) : 0;
+
+   return csr;
+}
+
 /*
  * Load an endpoint's FIFO
  */
@@ -2278,6 +2310,16 @@ static void musb_deassert_reset(struct work_struct *work)
else
musb->io.write_fifo = musb_default_write_fifo;
 
+   if (musb->ops->get_toggle)
+   musb->io.get_toggle = musb->ops->get_toggle;
+   else
+   musb->io.get_toggle = musb_default_get_toggle;
+
+   if (musb->ops->set_toggle)
+   musb->io.set_toggle = musb->ops->set_toggle;
+   else
+   musb->io.set_toggle = musb_default_set_toggle;
+
if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7..9f5a69c 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -27,6 +27,7 @@
 struct musb;
 struct musb_hw_ep;
 struct musb_ep;
+struct musb_qh;
 
 /* Helper defines for struct musb->hwvers */
 #define MUSB_HWVERS_MAJOR(x)   ((x >> 10) & 0x1f)
@@ -123,6 +124,8 @@ enum musb_g_ep0_state {
  * @writew:write 16 bits
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
+ * @get_toggle:platform specific get toggle function
+ * @set_toggle:platform specific set toggle function
  * @dma_init:  platform specific dma init function
  * @dma_exit:  platform specific dma exit function
  * @init:  turns on clocks, sets up platform-specific registers, etc
@@ -167,6 +170,8 @@ struct musb_platform_ops {
void(*writew)(void __iomem *addr, unsigned offset, u16 data);
void(*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void(*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
+   u16 (*get_toggle)(struct musb_qh *qh, int is_out);
+   u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
struct dma_controller *
(*dma_init) (struct musb *musb, void __iomem *base);
void(*dma_exit)(struct dma_controller *c);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index eb308ec..ca866bc 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -286,26 +286,6 @@ static void musb_giveback(struct musb *musb, struct urb 
*urb, int status)
spin_lock(&musb->lock);
 }
 
-/* For bulk/interrupt endpoints only */
-static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
-   struct urb *urb)
-{
-   void __iomem*epio = qh->hw_ep->regs;
-   u16 csr;
-
-   /*
-* FIXME: the current Mentor DMA code seems to have
-* problems getting toggle correct.
-*/
-
-   if (is_in)
-   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
-   else
-   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
-
-   usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
-}
-
 /*
  * Advance this hardware endpoint's queue, completing the specified URB and
  * advancing t

[PATCH v7 6/6] usb: musb: Add support for MediaTek musb controller

2019-08-30 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
changes in v7:
1. no changes

changes in v6:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode
3. Remove set vbus function

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
2. Make musb_clearb/w() return the value of musb_readb/w()
3. Add driver to get child nodes of usb connector and extcon device

changes in v4:
1. no changes

changes in v3:
suggested by Bin:
1. Remove 'u8/u16 data' parameter in clearb/w() hooks
2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status

changes in v2:
suggested by Bin:
1. Add summarize of MediaTek musb controller differences in the commit log
2. Add "|| COMPILE_TEST" in Kconfig
3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
4. Replace musb_readl() with musb_readw() to read 16bit toggle register
---
 drivers/usb/musb/Kconfig|   9 +-
 drivers/usb/musb/Makefile   |   1 +
 drivers/usb/musb/mediatek.c | 582 
 3 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 52f8e2b..767c5da 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -116,6 +116,13 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB=n || USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+   select USB_ROLE_SWITCH
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -142,7 +149,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..3df8d7e
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+#define MTK_TOGGLE_EN  GENMASK(15, 0)
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   enum usb_role role;
+   struct usb_role_switch *role_sw;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+

[PATCH v7 2/6] arm: dts: mt2701: Add usb2 device nodes

2019-08-30 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
changes in v7:
1. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
1. Modify usb connector child node

changes in v5:
1. Add usb connector child node

changes in v4:
1. no changes

changes in v3:
1. no changes

changes in v2:
1. Remove phy-names
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index 88f8fd2..05ba43c 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -61,6 +62,15 @@
>;
default-brightness-level = <9>;
};
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -230,3 +240,14 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   status = "okay";
+   connector{
+   compatible = "gpio-usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 51e1305..80a3b55 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -671,6 +671,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH v7 5/6] usb: musb: Add musb_clearb/w() interface

2019-08-30 Thread min.guo
From: Min Guo 

Delete the const attribute of addr parameter in readb/w/l hooks, these
changes are for implementing clearing W1C registers.
Replace musb_readb/w with musb_clearb/w to clear the interrupt status.

Signed-off-by: Min Guo 
---
changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 32 +++-
 drivers/usb/musb/musb_core.h |  8 ++--
 drivers/usb/musb/musb_io.h   |  8 +---
 drivers/usb/musb/musbhsdma.c |  2 +-
 drivers/usb/musb/sunxi.c |  4 ++--
 drivers/usb/musb/tusb6010.c  |  2 +-
 6 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 491d361..8528726 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -246,7 +246,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset)
return 0x80 + (0x08 * epnum) + offset;
 }
 
-static u8 musb_default_readb(const void __iomem *addr, unsigned offset)
+static u8 musb_default_readb(void __iomem *addr, unsigned offset)
 {
u8 data =  __raw_readb(addr + offset);
 
@@ -260,7 +260,7 @@ static void musb_default_writeb(void __iomem *addr, 
unsigned offset, u8 data)
__raw_writeb(data, addr + offset);
 }
 
-static u16 musb_default_readw(const void __iomem *addr, unsigned offset)
+static u16 musb_default_readw(void __iomem *addr, unsigned offset)
 {
u16 data = __raw_readw(addr + offset);
 
@@ -396,19 +396,25 @@ static void musb_default_read_fifo(struct musb_hw_ep 
*hw_ep, u16 len, u8 *dst)
 /*
  * Old style IO functions
  */
-u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readb);
 
 void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
 EXPORT_SYMBOL_GPL(musb_writeb);
 
-u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+u8 (*musb_clearb)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearb);
+
+u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readw);
 
 void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
 EXPORT_SYMBOL_GPL(musb_writew);
 
-u32 musb_readl(const void __iomem *addr, unsigned offset)
+u16 (*musb_clearw)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearw);
+
+u32 musb_readl(void __iomem *addr, unsigned offset)
 {
u32 data = __raw_readl(addr + offset);
 
@@ -1047,7 +1053,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 
int_usb,
 static void musb_disable_interrupts(struct musb *musb)
 {
void __iomem*mbase = musb->mregs;
-   u16 temp;
 
/* disable interrupts */
musb_writeb(mbase, MUSB_INTRUSBE, 0);
@@ -1057,9 +1062,9 @@ static void musb_disable_interrupts(struct musb *musb)
musb_writew(mbase, MUSB_INTRRXE, 0);
 
/*  flush pending interrupts */
-   temp = musb_readb(mbase, MUSB_INTRUSB);
-   temp = musb_readw(mbase, MUSB_INTRTX);
-   temp = musb_readw(mbase, MUSB_INTRRX);
+   musb_clearb(mbase, MUSB_INTRUSB);
+   musb_clearw(mbase, MUSB_INTRTX);
+   musb_clearw(mbase, MUSB_INTRRX);
 }
 
 static void musb_enable_interrupts(struct musb *musb)
@@ -2285,10 +2290,19 @@ static void musb_deassert_reset(struct work_struct 
*work)
musb_readb = musb->ops->readb;
if (musb->ops->writeb)
musb_writeb = musb->ops->writeb;
+   if (musb->ops->clearb)
+   musb_clearb = musb->ops->clearb;
+   else
+   musb_clearb = musb_readb;
+
if (musb->ops->readw)
musb_readw = musb->ops->readw;
if (musb->ops->writew)
musb_writew = musb->ops->writew;
+   if (musb->ops->clearw)
+   musb_clearw = musb->ops->clearw;
+   else
+   musb_clearw = musb_readw;
 
 #ifndef CONFIG_MUSB_PIO_ONLY
if (!musb->ops->dma_init || !musb->ops->dma_exit) {
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 9f5a69c..0d9a35f 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -120,8 +120,10 @@ enum musb_g_ep0_state {
  * @fifo_offset: returns the fifo offset
  * @readb: read 8 bits
  * @writeb:write 8 bits
+ * @clearb:could be clear-on-readb or W1C
  * @readw: read 16 bits
  * @writew:write 16 bits
+ * @clearw:could be clear-on-readw or W1C
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
  * @get_toggle:platform specific get toggle function
@@ -164,10 +166,12 @@ struct musb_platform_ops {
u16 fifo_mode;
u32 (*fifo_offset)(u8 epnum);
u32 (*busctl_offset)(u8 epnum, u16 offset);
-   u8  (*readb)(const void __iomem *addr, unsigned offset);
+   u8  (*readb)(void __iomem *addr, un

[PATCH RESEND v7 4/6] usb: musb: Add noirq type of dma create interface

2019-10-17 Thread min.guo
From: Min Guo 

Add noirq type of dma create interface for platform which do not
have dedicated DMA interrupt line, move musbhsdma macro definition
to musb_dma.h

Signed-off-by: Min Guo 
---
changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_dma.h  |  9 
 drivers/usb/musb/musbhsdma.c | 54 ++--
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 8f60271..05103ea3 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -35,6 +35,12 @@
  *whether shared with the Inventra core or separate.
  */
 
+#define MUSB_HSDMA_BASE0x200
+#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL 0x4
+#define MUSB_HSDMA_ADDRESS 0x8
+#define MUSB_HSDMA_COUNT   0xc
+
 #defineDMA_ADDR_INVALID(~(dma_addr_t)0)
 
 #ifdef CONFIG_MUSB_PIO_ONLY
@@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct 
dma_controller *d) { }
 extern struct dma_controller *
 musbhs_dma_controller_create(struct musb *musb, void __iomem *base);
 extern void musbhs_dma_controller_destroy(struct dma_controller *c);
+extern struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base);
+extern irqreturn_t dma_controller_irq(int irq, void *private_data);
 
 extern struct dma_controller *
 tusb_dma_controller_create(struct musb *musb, void __iomem *base);
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 5fc6825..d549c0b 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -10,12 +10,7 @@
 #include 
 #include 
 #include "musb_core.h"
-
-#define MUSB_HSDMA_BASE0x200
-#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL 0x4
-#define MUSB_HSDMA_ADDRESS 0x8
-#define MUSB_HSDMA_COUNT   0xc
+#include "musb_dma.h"
 
 #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)  \
(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
@@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel)
return 0;
 }
 
-static irqreturn_t dma_controller_irq(int irq, void *private_data)
+irqreturn_t dma_controller_irq(int irq, void *private_data)
 {
struct musb_dma_controller *controller = private_data;
struct musb *musb = controller->private_data;
@@ -383,6 +378,7 @@ static irqreturn_t dma_controller_irq(int irq, void 
*private_data)
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
 }
+EXPORT_SYMBOL_GPL(dma_controller_irq);
 
 void musbhs_dma_controller_destroy(struct dma_controller *c)
 {
@@ -398,18 +394,10 @@ void musbhs_dma_controller_destroy(struct dma_controller 
*c)
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy);
 
-struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
-   void __iomem *base)
+static struct musb_dma_controller *
+dma_controller_alloc(struct musb *musb, void __iomem *base)
 {
struct musb_dma_controller *controller;
-   struct device *dev = musb->controller;
-   struct platform_device *pdev = to_platform_device(dev);
-   int irq = platform_get_irq_byname(pdev, "dma");
-
-   if (irq <= 0) {
-   dev_err(dev, "No DMA interrupt line!\n");
-   return NULL;
-   }
 
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
@@ -423,6 +411,25 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
controller->controller.channel_release = dma_channel_release;
controller->controller.channel_program = dma_channel_program;
controller->controller.channel_abort = dma_channel_abort;
+   return controller;
+}
+
+struct dma_controller *
+musbhs_dma_controller_create(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+   struct device *dev = musb->controller;
+   struct platform_device *pdev = to_platform_device(dev);
+   int irq = platform_get_irq_byname(pdev, "dma");
+
+   if (irq <= 0) {
+   dev_err(dev, "No DMA interrupt line!\n");
+   return NULL;
+   }
+
+   controller = dma_controller_alloc(musb, base);
+   if (!controller)
+   return NULL;
 
if (request_irq(irq, dma_controller_irq, 0,
dev_name(musb->controller), &controller->controller)) {
@@ -437,3 +444,16 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
return &controller->controller;
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_create);
+
+struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base)
+{
+   s

[PATCH RESEND v7 3/6] usb: musb: Add get/set toggle hooks

2019-10-17 Thread min.guo
From: Min Guo 

Add get/set toggle hooks in struct musb_io and struct musb_platform_ops
for special platform; remove function musb_save_toggle, use the set/get
callback to handle toggle.

Signed-off-by: Min Guo 
---
changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 42 
 drivers/usb/musb/musb_core.h |  5 +
 drivers/usb/musb/musb_host.c | 46 ++--
 drivers/usb/musb/musb_io.h   |  4 
 4 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index bd63450af..690b8da 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -274,6 +274,38 @@ static void musb_default_writew(void __iomem *addr, 
unsigned offset, u16 data)
__raw_writew(data, addr + offset);
 }
 
+static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out)
+{
+   void __iomem *epio = qh->hw_ep->regs;
+   u16 csr;
+
+   if (is_out)
+   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+   else
+   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+
+   return csr;
+}
+
+static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out,
+  struct urb *urb)
+{
+   u16 csr;
+   u16 toggle;
+
+   toggle = usb_gettoggle(urb->dev, qh->epnum, is_out);
+
+   if (is_out)
+   csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
+   | MUSB_TXCSR_H_DATATOGGLE)
+   : MUSB_TXCSR_CLRDATATOG;
+   else
+   csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
+   | MUSB_RXCSR_H_DATATOGGLE) : 0;
+
+   return csr;
+}
+
 /*
  * Load an endpoint's FIFO
  */
@@ -2271,6 +2303,16 @@ static void musb_deassert_reset(struct work_struct *work)
else
musb->io.write_fifo = musb_default_write_fifo;
 
+   if (musb->ops->get_toggle)
+   musb->io.get_toggle = musb->ops->get_toggle;
+   else
+   musb->io.get_toggle = musb_default_get_toggle;
+
+   if (musb->ops->set_toggle)
+   musb->io.set_toggle = musb->ops->set_toggle;
+   else
+   musb->io.set_toggle = musb_default_set_toggle;
+
if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7..9f5a69c 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -27,6 +27,7 @@
 struct musb;
 struct musb_hw_ep;
 struct musb_ep;
+struct musb_qh;
 
 /* Helper defines for struct musb->hwvers */
 #define MUSB_HWVERS_MAJOR(x)   ((x >> 10) & 0x1f)
@@ -123,6 +124,8 @@ enum musb_g_ep0_state {
  * @writew:write 16 bits
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
+ * @get_toggle:platform specific get toggle function
+ * @set_toggle:platform specific set toggle function
  * @dma_init:  platform specific dma init function
  * @dma_exit:  platform specific dma exit function
  * @init:  turns on clocks, sets up platform-specific registers, etc
@@ -167,6 +170,8 @@ struct musb_platform_ops {
void(*writew)(void __iomem *addr, unsigned offset, u16 data);
void(*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void(*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
+   u16 (*get_toggle)(struct musb_qh *qh, int is_out);
+   u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
struct dma_controller *
(*dma_init) (struct musb *musb, void __iomem *base);
void(*dma_exit)(struct dma_controller *c);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 5a44b70..886c9b6 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -286,26 +286,6 @@ static void musb_giveback(struct musb *musb, struct urb 
*urb, int status)
spin_lock(&musb->lock);
 }
 
-/* For bulk/interrupt endpoints only */
-static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
-   struct urb *urb)
-{
-   void __iomem*epio = qh->hw_ep->regs;
-   u16 csr;
-
-   /*
-* FIXME: the current Mentor DMA code seems to have
-* problems getting toggle correct.
-*/
-
-   if (is_in)
-   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
-   else
-   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
-
-   usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
-}
-
 /*
  * Advance this hardware endpoint's queue, completing the specified URB and
  * advancing

[PATCH RESEND v7 0/6] Add MediaTek MUSB Controller Driver

2019-10-17 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v7:
changes of dt-bindings and DTS:
1. Change compatible string
2. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
changes of dt-bindings:
1. Modify usb connector child node
changes of DTS:
1. Modify usb connector child node
changes of driver:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode,
   depends on [1]
3. Remove set vbus function

[1] [v6,09/10] usb: roles: add USB Type-B GPIO connector driver
https://patchwork.kernel.org/patch/10966361/

changes in v5:
changes of dt-bindings suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node
changes of DTS:
1. Add usb connector child node
changes of driver suggested by Bin:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts
2. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
3. Make musb_clearb/w() return the value of musb_readb/w()

changes in v4:
changes of dt-bindings suggested by Sergei:
1. String alignment
changes of driver suggested by Tony and Bin:
1. Add a new patch for set/get_toggle()
2. Add a new patch for noirq type of dma
3. Add a new patch musb_clearb/w()
4. Abondon patch "usb: musb: Delete the const attribute of addr parameter in 
readb/w/l hooks"

changes in v3:
changes of driver suggested by Bin:
1. Add a new patch for musb_readb/w/l() to remove const attribute 
2. Use is_out as function parameter in set_toggle/get_toggle() hooks
3. Remove 'u8/u16 data' parameter in clearb/w() hooks
4. Remove musb_default_clearb/w()
5. Replace musb_readb/w() with musb_clearb/w() to clear pending interrupts 
6. Add comments to clearb/w() hooks
7. Replace musb_save_toggle() with musb->io.get_toggle()
8. Replace musb_set_toggle() with musb->io.set_toggle()

changes in v2:
changes of dt-bindings suggested by Rob and Bin:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (6):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Add get/set toggle hooks
  usb: musb: Add noirq type of dma create interface
  usb: musb: Add musb_clearb/w() interface
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  55 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   9 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 582 +
 drivers/usb/musb/musb_core.c   |  74 ++-
 drivers/usb/musb/musb_core.h   |  13 +-
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  46 +-
 drivers/usb/musb/musb_io.h |  12 +-
 drivers/usb/musb/musbhsdma.c   |  56 +-
 drivers/usb/musb/sunxi.c   |   4 +-
 drivers/usb/musb/tusb6010.c|   2 +-
 14 files changed, 845 insertions(+), 72 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH RESEND v7 6/6] usb: musb: Add support for MediaTek musb controller

2019-10-17 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
changes in v7:
1. no changes

changes in v6:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode
3. Remove set vbus function

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
2. Make musb_clearb/w() return the value of musb_readb/w()
3. Add driver to get child nodes of usb connector and extcon device

changes in v4:
1. no changes

changes in v3:
suggested by Bin:
1. Remove 'u8/u16 data' parameter in clearb/w() hooks
2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status

changes in v2:
suggested by Bin:
1. Add summarize of MediaTek musb controller differences in the commit log
2. Add "|| COMPILE_TEST" in Kconfig
3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
4. Replace musb_readl() with musb_readw() to read 16bit toggle register
---
 drivers/usb/musb/Kconfig|   9 +-
 drivers/usb/musb/Makefile   |   1 +
 drivers/usb/musb/mediatek.c | 582 
 3 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 52f8e2b..767c5da 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -116,6 +116,13 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB=n || USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+   select USB_ROLE_SWITCH
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -142,7 +149,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..3df8d7e
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+#define MTK_TOGGLE_EN  GENMASK(15, 0)
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   enum usb_role role;
+   struct usb_role_switch *role_sw;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+

[PATCH RESEND v7 2/6] arm: dts: mt2701: Add usb2 device nodes

2019-10-17 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
changes in v7:
1. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
1. Modify usb connector child node

changes in v5:
1. Add usb connector child node

changes in v4:
1. no changes

changes in v3:
1. no changes

changes in v2:
1. Remove phy-names
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index 88f8fd2..05ba43c 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -61,6 +62,15 @@
>;
default-brightness-level = <9>;
};
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -230,3 +240,14 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   status = "okay";
+   connector{
+   compatible = "gpio-usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 51e1305..80a3b55 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -671,6 +671,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH RESEND v7 1/6] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-10-17 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
---
changes in v7:
1. Modify compatible as
- compatible : should be one of:
   "mediatek,mt2701-musb"
   ...
   followed by "mediatek,mtk-musb"
2. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
1. Modify usb connector child node

changes in v5:
suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node

changes in v4:
suggested by Sergei:
1. String alignment

changes in v3:
1. no changes

changes in v2:
suggested by Bin:
1. Modify DRC to DRD
suggested by Rob:
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 55 ++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..e53c482
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,55 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be one of:
+ "mediatek,mt2701-musb"
+ ...
+ followed by "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+ the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+ refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+ each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+ for clocks of controller
+
+Optional properties:
+ - power-domains   : a phandle to USB power domain node to control USB's
+ MTCMOS
+
+Required child nodes:
+ usb connector node as defined in bindings/connector/usb-connector.txt
+Optional properties:
+ - id-gpios: input GPIO for USB ID pin.
+ - vbus-gpios  : input GPIO for USB VBUS pin.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+ dual-role mode
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   connector{
+   compatible = "gpio-usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
-- 
1.9.1



[PATCH RESEND v7 5/6] usb: musb: Add musb_clearb/w() interface

2019-10-17 Thread min.guo
From: Min Guo 

Delete the const attribute of addr parameter in readb/w/l hooks, these
changes are for implementing clearing W1C registers.
Replace musb_readb/w with musb_clearb/w to clear the interrupt status.

Signed-off-by: Min Guo 
---
changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 32 +++-
 drivers/usb/musb/musb_core.h |  8 ++--
 drivers/usb/musb/musb_io.h   |  8 +---
 drivers/usb/musb/musbhsdma.c |  2 +-
 drivers/usb/musb/sunxi.c |  4 ++--
 drivers/usb/musb/tusb6010.c  |  2 +-
 6 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 690b8da..9d4399d 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -246,7 +246,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset)
return 0x80 + (0x08 * epnum) + offset;
 }
 
-static u8 musb_default_readb(const void __iomem *addr, unsigned offset)
+static u8 musb_default_readb(void __iomem *addr, unsigned offset)
 {
u8 data =  __raw_readb(addr + offset);
 
@@ -260,7 +260,7 @@ static void musb_default_writeb(void __iomem *addr, 
unsigned offset, u8 data)
__raw_writeb(data, addr + offset);
 }
 
-static u16 musb_default_readw(const void __iomem *addr, unsigned offset)
+static u16 musb_default_readw(void __iomem *addr, unsigned offset)
 {
u16 data = __raw_readw(addr + offset);
 
@@ -396,19 +396,25 @@ static void musb_default_read_fifo(struct musb_hw_ep 
*hw_ep, u16 len, u8 *dst)
 /*
  * Old style IO functions
  */
-u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readb);
 
 void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
 EXPORT_SYMBOL_GPL(musb_writeb);
 
-u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+u8 (*musb_clearb)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearb);
+
+u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readw);
 
 void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
 EXPORT_SYMBOL_GPL(musb_writew);
 
-u32 musb_readl(const void __iomem *addr, unsigned offset)
+u16 (*musb_clearw)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearw);
+
+u32 musb_readl(void __iomem *addr, unsigned offset)
 {
u32 data = __raw_readl(addr + offset);
 
@@ -1047,7 +1053,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 
int_usb,
 static void musb_disable_interrupts(struct musb *musb)
 {
void __iomem*mbase = musb->mregs;
-   u16 temp;
 
/* disable interrupts */
musb_writeb(mbase, MUSB_INTRUSBE, 0);
@@ -1057,9 +1062,9 @@ static void musb_disable_interrupts(struct musb *musb)
musb_writew(mbase, MUSB_INTRRXE, 0);
 
/*  flush pending interrupts */
-   temp = musb_readb(mbase, MUSB_INTRUSB);
-   temp = musb_readw(mbase, MUSB_INTRTX);
-   temp = musb_readw(mbase, MUSB_INTRRX);
+   musb_clearb(mbase, MUSB_INTRUSB);
+   musb_clearw(mbase, MUSB_INTRTX);
+   musb_clearw(mbase, MUSB_INTRRX);
 }
 
 static void musb_enable_interrupts(struct musb *musb)
@@ -2278,10 +2283,19 @@ static void musb_deassert_reset(struct work_struct 
*work)
musb_readb = musb->ops->readb;
if (musb->ops->writeb)
musb_writeb = musb->ops->writeb;
+   if (musb->ops->clearb)
+   musb_clearb = musb->ops->clearb;
+   else
+   musb_clearb = musb_readb;
+
if (musb->ops->readw)
musb_readw = musb->ops->readw;
if (musb->ops->writew)
musb_writew = musb->ops->writew;
+   if (musb->ops->clearw)
+   musb_clearw = musb->ops->clearw;
+   else
+   musb_clearw = musb_readw;
 
 #ifndef CONFIG_MUSB_PIO_ONLY
if (!musb->ops->dma_init || !musb->ops->dma_exit) {
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 9f5a69c..0d9a35f 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -120,8 +120,10 @@ enum musb_g_ep0_state {
  * @fifo_offset: returns the fifo offset
  * @readb: read 8 bits
  * @writeb:write 8 bits
+ * @clearb:could be clear-on-readb or W1C
  * @readw: read 16 bits
  * @writew:write 16 bits
+ * @clearw:could be clear-on-readw or W1C
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
  * @get_toggle:platform specific get toggle function
@@ -164,10 +166,12 @@ struct musb_platform_ops {
u16 fifo_mode;
u32 (*fifo_offset)(u8 epnum);
u32 (*busctl_offset)(u8 epnum, u16 offset);
-   u8  (*readb)(const void __iomem *addr, unsigned offset);
+   u8  (*readb)(void __iomem *addr, un

[PATCH v8 3/6] usb: musb: Add get/set toggle hooks

2019-10-17 Thread min.guo
From: Min Guo 

Add get/set toggle hooks in struct musb_io and struct musb_platform_ops
for special platform; remove function musb_save_toggle, use the set/get
callback to handle toggle.

Signed-off-by: Min Guo 
---
changes in v8:
1. no changes

changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 42 
 drivers/usb/musb/musb_core.h |  5 +
 drivers/usb/musb/musb_host.c | 46 ++--
 drivers/usb/musb/musb_io.h   |  4 
 4 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index bd63450af..690b8da 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -274,6 +274,38 @@ static void musb_default_writew(void __iomem *addr, 
unsigned offset, u16 data)
__raw_writew(data, addr + offset);
 }
 
+static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out)
+{
+   void __iomem *epio = qh->hw_ep->regs;
+   u16 csr;
+
+   if (is_out)
+   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+   else
+   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+
+   return csr;
+}
+
+static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out,
+  struct urb *urb)
+{
+   u16 csr;
+   u16 toggle;
+
+   toggle = usb_gettoggle(urb->dev, qh->epnum, is_out);
+
+   if (is_out)
+   csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
+   | MUSB_TXCSR_H_DATATOGGLE)
+   : MUSB_TXCSR_CLRDATATOG;
+   else
+   csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
+   | MUSB_RXCSR_H_DATATOGGLE) : 0;
+
+   return csr;
+}
+
 /*
  * Load an endpoint's FIFO
  */
@@ -2271,6 +2303,16 @@ static void musb_deassert_reset(struct work_struct *work)
else
musb->io.write_fifo = musb_default_write_fifo;
 
+   if (musb->ops->get_toggle)
+   musb->io.get_toggle = musb->ops->get_toggle;
+   else
+   musb->io.get_toggle = musb_default_get_toggle;
+
+   if (musb->ops->set_toggle)
+   musb->io.set_toggle = musb->ops->set_toggle;
+   else
+   musb->io.set_toggle = musb_default_set_toggle;
+
if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7..9f5a69c 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -27,6 +27,7 @@
 struct musb;
 struct musb_hw_ep;
 struct musb_ep;
+struct musb_qh;
 
 /* Helper defines for struct musb->hwvers */
 #define MUSB_HWVERS_MAJOR(x)   ((x >> 10) & 0x1f)
@@ -123,6 +124,8 @@ enum musb_g_ep0_state {
  * @writew:write 16 bits
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
+ * @get_toggle:platform specific get toggle function
+ * @set_toggle:platform specific set toggle function
  * @dma_init:  platform specific dma init function
  * @dma_exit:  platform specific dma exit function
  * @init:  turns on clocks, sets up platform-specific registers, etc
@@ -167,6 +170,8 @@ struct musb_platform_ops {
void(*writew)(void __iomem *addr, unsigned offset, u16 data);
void(*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void(*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
+   u16 (*get_toggle)(struct musb_qh *qh, int is_out);
+   u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
struct dma_controller *
(*dma_init) (struct musb *musb, void __iomem *base);
void(*dma_exit)(struct dma_controller *c);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 5a44b70..886c9b6 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -286,26 +286,6 @@ static void musb_giveback(struct musb *musb, struct urb 
*urb, int status)
spin_lock(&musb->lock);
 }
 
-/* For bulk/interrupt endpoints only */
-static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
-   struct urb *urb)
-{
-   void __iomem*epio = qh->hw_ep->regs;
-   u16 csr;
-
-   /*
-* FIXME: the current Mentor DMA code seems to have
-* problems getting toggle correct.
-*/
-
-   if (is_in)
-   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
-   else
-   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
-
-   usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
-}
-
 /*
  * Advance this hardware endpoint's queue, completing the s

[PATCH v8 4/6] usb: musb: Add noirq type of dma create interface

2019-10-17 Thread min.guo
From: Min Guo 

Add noirq type of dma create interface for platform which do not
have dedicated DMA interrupt line, move musbhsdma macro definition
to musb_dma.h

Signed-off-by: Min Guo 
---
changes in v8:
1. no changes

changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_dma.h  |  9 
 drivers/usb/musb/musbhsdma.c | 54 ++--
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 8f60271..05103ea3 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -35,6 +35,12 @@
  *whether shared with the Inventra core or separate.
  */
 
+#define MUSB_HSDMA_BASE0x200
+#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL 0x4
+#define MUSB_HSDMA_ADDRESS 0x8
+#define MUSB_HSDMA_COUNT   0xc
+
 #defineDMA_ADDR_INVALID(~(dma_addr_t)0)
 
 #ifdef CONFIG_MUSB_PIO_ONLY
@@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct 
dma_controller *d) { }
 extern struct dma_controller *
 musbhs_dma_controller_create(struct musb *musb, void __iomem *base);
 extern void musbhs_dma_controller_destroy(struct dma_controller *c);
+extern struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base);
+extern irqreturn_t dma_controller_irq(int irq, void *private_data);
 
 extern struct dma_controller *
 tusb_dma_controller_create(struct musb *musb, void __iomem *base);
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 5fc6825..d549c0b 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -10,12 +10,7 @@
 #include 
 #include 
 #include "musb_core.h"
-
-#define MUSB_HSDMA_BASE0x200
-#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL 0x4
-#define MUSB_HSDMA_ADDRESS 0x8
-#define MUSB_HSDMA_COUNT   0xc
+#include "musb_dma.h"
 
 #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)  \
(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
@@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel)
return 0;
 }
 
-static irqreturn_t dma_controller_irq(int irq, void *private_data)
+irqreturn_t dma_controller_irq(int irq, void *private_data)
 {
struct musb_dma_controller *controller = private_data;
struct musb *musb = controller->private_data;
@@ -383,6 +378,7 @@ static irqreturn_t dma_controller_irq(int irq, void 
*private_data)
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
 }
+EXPORT_SYMBOL_GPL(dma_controller_irq);
 
 void musbhs_dma_controller_destroy(struct dma_controller *c)
 {
@@ -398,18 +394,10 @@ void musbhs_dma_controller_destroy(struct dma_controller 
*c)
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy);
 
-struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
-   void __iomem *base)
+static struct musb_dma_controller *
+dma_controller_alloc(struct musb *musb, void __iomem *base)
 {
struct musb_dma_controller *controller;
-   struct device *dev = musb->controller;
-   struct platform_device *pdev = to_platform_device(dev);
-   int irq = platform_get_irq_byname(pdev, "dma");
-
-   if (irq <= 0) {
-   dev_err(dev, "No DMA interrupt line!\n");
-   return NULL;
-   }
 
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
@@ -423,6 +411,25 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
controller->controller.channel_release = dma_channel_release;
controller->controller.channel_program = dma_channel_program;
controller->controller.channel_abort = dma_channel_abort;
+   return controller;
+}
+
+struct dma_controller *
+musbhs_dma_controller_create(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+   struct device *dev = musb->controller;
+   struct platform_device *pdev = to_platform_device(dev);
+   int irq = platform_get_irq_byname(pdev, "dma");
+
+   if (irq <= 0) {
+   dev_err(dev, "No DMA interrupt line!\n");
+   return NULL;
+   }
+
+   controller = dma_controller_alloc(musb, base);
+   if (!controller)
+   return NULL;
 
if (request_irq(irq, dma_controller_irq, 0,
dev_name(musb->controller), &controller->controller)) {
@@ -437,3 +444,16 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
return &controller->controller;
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_create);
+
+struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, vo

[PATCH v8 0/6] Add MediaTek MUSB Controller Driver

2019-10-17 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v8:
changes of dt-bindings:
1. Add reviewed by Rob

changes in v7:
changes of dt-bindings and DTS:
1. Change compatible string
2. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
changes of dt-bindings:
1. Modify usb connector child node
changes of DTS:
1. Modify usb connector child node
changes of driver:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode,
   depends on [1]
3. Remove set vbus function

[1] [v6,09/10] usb: roles: add USB Type-B GPIO connector driver
https://patchwork.kernel.org/patch/10966361/

changes in v5:
changes of dt-bindings suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node
changes of DTS:
1. Add usb connector child node
changes of driver suggested by Bin:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts
2. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
3. Make musb_clearb/w() return the value of musb_readb/w()

changes in v4:
changes of dt-bindings suggested by Sergei:
1. String alignment
changes of driver suggested by Tony and Bin:
1. Add a new patch for set/get_toggle()
2. Add a new patch for noirq type of dma
3. Add a new patch musb_clearb/w()
4. Abondon patch "usb: musb: Delete the const attribute of addr parameter in 
readb/w/l hooks"

changes in v3:
changes of driver suggested by Bin:
1. Add a new patch for musb_readb/w/l() to remove const attribute 
2. Use is_out as function parameter in set_toggle/get_toggle() hooks
3. Remove 'u8/u16 data' parameter in clearb/w() hooks
4. Remove musb_default_clearb/w()
5. Replace musb_readb/w() with musb_clearb/w() to clear pending interrupts 
6. Add comments to clearb/w() hooks
7. Replace musb_save_toggle() with musb->io.get_toggle()
8. Replace musb_set_toggle() with musb->io.set_toggle()

changes in v2:
changes of dt-bindings suggested by Rob and Bin:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (6):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Add get/set toggle hooks
  usb: musb: Add noirq type of dma create interface
  usb: musb: Add musb_clearb/w() interface
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  55 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   9 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 582 +
 drivers/usb/musb/musb_core.c   |  74 ++-
 drivers/usb/musb/musb_core.h   |  13 +-
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  46 +-
 drivers/usb/musb/musb_io.h |  12 +-
 drivers/usb/musb/musbhsdma.c   |  56 +-
 drivers/usb/musb/sunxi.c   |   4 +-
 drivers/usb/musb/tusb6010.c|   2 +-
 14 files changed, 845 insertions(+), 72 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH v8 5/6] usb: musb: Add musb_clearb/w() interface

2019-10-17 Thread min.guo
From: Min Guo 

Delete the const attribute of addr parameter in readb/w/l hooks, these
changes are for implementing clearing W1C registers.
Replace musb_readb/w with musb_clearb/w to clear the interrupt status.

Signed-off-by: Min Guo 
---
changes in v8:
1. no changes

changes in v7:
1. no changes

changes in v6:
1. no changes

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 32 +++-
 drivers/usb/musb/musb_core.h |  8 ++--
 drivers/usb/musb/musb_io.h   |  8 +---
 drivers/usb/musb/musbhsdma.c |  2 +-
 drivers/usb/musb/sunxi.c |  4 ++--
 drivers/usb/musb/tusb6010.c  |  2 +-
 6 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 690b8da..9d4399d 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -246,7 +246,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset)
return 0x80 + (0x08 * epnum) + offset;
 }
 
-static u8 musb_default_readb(const void __iomem *addr, unsigned offset)
+static u8 musb_default_readb(void __iomem *addr, unsigned offset)
 {
u8 data =  __raw_readb(addr + offset);
 
@@ -260,7 +260,7 @@ static void musb_default_writeb(void __iomem *addr, 
unsigned offset, u8 data)
__raw_writeb(data, addr + offset);
 }
 
-static u16 musb_default_readw(const void __iomem *addr, unsigned offset)
+static u16 musb_default_readw(void __iomem *addr, unsigned offset)
 {
u16 data = __raw_readw(addr + offset);
 
@@ -396,19 +396,25 @@ static void musb_default_read_fifo(struct musb_hw_ep 
*hw_ep, u16 len, u8 *dst)
 /*
  * Old style IO functions
  */
-u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readb);
 
 void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
 EXPORT_SYMBOL_GPL(musb_writeb);
 
-u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+u8 (*musb_clearb)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearb);
+
+u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readw);
 
 void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
 EXPORT_SYMBOL_GPL(musb_writew);
 
-u32 musb_readl(const void __iomem *addr, unsigned offset)
+u16 (*musb_clearw)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearw);
+
+u32 musb_readl(void __iomem *addr, unsigned offset)
 {
u32 data = __raw_readl(addr + offset);
 
@@ -1047,7 +1053,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 
int_usb,
 static void musb_disable_interrupts(struct musb *musb)
 {
void __iomem*mbase = musb->mregs;
-   u16 temp;
 
/* disable interrupts */
musb_writeb(mbase, MUSB_INTRUSBE, 0);
@@ -1057,9 +1062,9 @@ static void musb_disable_interrupts(struct musb *musb)
musb_writew(mbase, MUSB_INTRRXE, 0);
 
/*  flush pending interrupts */
-   temp = musb_readb(mbase, MUSB_INTRUSB);
-   temp = musb_readw(mbase, MUSB_INTRTX);
-   temp = musb_readw(mbase, MUSB_INTRRX);
+   musb_clearb(mbase, MUSB_INTRUSB);
+   musb_clearw(mbase, MUSB_INTRTX);
+   musb_clearw(mbase, MUSB_INTRRX);
 }
 
 static void musb_enable_interrupts(struct musb *musb)
@@ -2278,10 +2283,19 @@ static void musb_deassert_reset(struct work_struct 
*work)
musb_readb = musb->ops->readb;
if (musb->ops->writeb)
musb_writeb = musb->ops->writeb;
+   if (musb->ops->clearb)
+   musb_clearb = musb->ops->clearb;
+   else
+   musb_clearb = musb_readb;
+
if (musb->ops->readw)
musb_readw = musb->ops->readw;
if (musb->ops->writew)
musb_writew = musb->ops->writew;
+   if (musb->ops->clearw)
+   musb_clearw = musb->ops->clearw;
+   else
+   musb_clearw = musb_readw;
 
 #ifndef CONFIG_MUSB_PIO_ONLY
if (!musb->ops->dma_init || !musb->ops->dma_exit) {
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 9f5a69c..0d9a35f 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -120,8 +120,10 @@ enum musb_g_ep0_state {
  * @fifo_offset: returns the fifo offset
  * @readb: read 8 bits
  * @writeb:write 8 bits
+ * @clearb:could be clear-on-readb or W1C
  * @readw: read 16 bits
  * @writew:write 16 bits
+ * @clearw:could be clear-on-readw or W1C
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
  * @get_toggle:platform specific get toggle function
@@ -164,10 +166,12 @@ struct musb_platform_ops {
u16 fifo_mode;
u32 (*fifo_offset)(u8 epnum);
u32 (*busctl_offset)(u8 epnum, u16 offset);
-   u8  (*readb)(const void __iomem *addr, unsigned offset);
+   u8  (

[PATCH v8 2/6] arm: dts: mt2701: Add usb2 device nodes

2019-10-17 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
changes in v8:
1. no changes

changes in v7:
1. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
1. Modify usb connector child node

changes in v5:
1. Add usb connector child node

changes in v4:
1. no changes

changes in v3:
1. no changes

changes in v2:
1. Remove phy-names
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index 88f8fd2..05ba43c 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -61,6 +62,15 @@
>;
default-brightness-level = <9>;
};
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -230,3 +240,14 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   status = "okay";
+   connector{
+   compatible = "gpio-usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 51e1305..80a3b55 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -671,6 +671,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH v8 6/6] usb: musb: Add support for MediaTek musb controller

2019-10-17 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
changes in v8:
1. no changes

changes in v7:
1. no changes

changes in v6:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode
3. Remove set vbus function

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
2. Make musb_clearb/w() return the value of musb_readb/w()
3. Add driver to get child nodes of usb connector and extcon device

changes in v4:
1. no changes

changes in v3:
suggested by Bin:
1. Remove 'u8/u16 data' parameter in clearb/w() hooks
2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status

changes in v2:
suggested by Bin:
1. Add summarize of MediaTek musb controller differences in the commit log
2. Add "|| COMPILE_TEST" in Kconfig
3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
4. Replace musb_readl() with musb_readw() to read 16bit toggle register
---
 drivers/usb/musb/Kconfig|   9 +-
 drivers/usb/musb/Makefile   |   1 +
 drivers/usb/musb/mediatek.c | 582 
 3 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 52f8e2b..767c5da 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -116,6 +116,13 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB=n || USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+   select USB_ROLE_SWITCH
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -142,7 +149,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..3df8d7e
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+#define MTK_TOGGLE_EN  GENMASK(15, 0)
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   enum usb_role role;
+   struct usb_role_switch *role_sw;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail t

[PATCH v8 1/6] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-10-17 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
Reviewed-by: Rob Herring 
---
changes in v8:
1. Add reviewed by Rob

changes in v7:
1. Modify compatible as
- compatible : should be one of:
   "mediatek,mt2701-musb"
   ...
   followed by "mediatek,mtk-musb"
2. Change usb connector child node compatible as "gpio-usb-b-connector" 

changes in v6:
1. Modify usb connector child node

changes in v5:
suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node

changes in v4:
suggested by Sergei:
1. String alignment

changes in v3:
1. no changes

changes in v2:
suggested by Bin:
1. Modify DRC to DRD
suggested by Rob:
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 55 ++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..e53c482
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,55 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be one of:
+ "mediatek,mt2701-musb"
+ ...
+ followed by "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+ the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+ refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+ each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+ for clocks of controller
+
+Optional properties:
+ - power-domains   : a phandle to USB power domain node to control USB's
+ MTCMOS
+
+Required child nodes:
+ usb connector node as defined in bindings/connector/usb-connector.txt
+Optional properties:
+ - id-gpios: input GPIO for USB ID pin.
+ - vbus-gpios  : input GPIO for USB VBUS pin.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+ dual-role mode
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   connector{
+   compatible = "gpio-usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
-- 
1.9.1



[PATCH v3 1/4] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-01-16 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 43 ++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..3e3f671
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,43 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+   the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+   refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+   each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+   for clocks of controller
+
+Optional properties:
+ - extcon : external connector for VBUS and IDPIN changes detection,
+   needed when supports dual-role mode.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+   dual-role mode.
+ - power-domains   : a phandle to USB power domain node to control USB's
+   MTCMOS
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+};
-- 
1.9.1



[PATCH v3 3/4] usb: musb: Delete the const attribute of addr parameter in readb/w/l hooks

2019-01-16 Thread min.guo
From: Min Guo 

These changes are for implementing clearing W1C registers.

Signed-off-by: Min Guo 
---
 drivers/usb/musb/musb_core.c | 10 +-
 drivers/usb/musb/musb_core.h |  4 ++--
 drivers/usb/musb/musb_io.h   |  6 +++---
 drivers/usb/musb/sunxi.c |  4 ++--
 drivers/usb/musb/tusb6010.c  |  2 +-
 5 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index b7d5627..d7a417b 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -246,7 +246,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset)
return 0x80 + (0x08 * epnum) + offset;
 }
 
-static u8 musb_default_readb(const void __iomem *addr, unsigned offset)
+static u8 musb_default_readb(void __iomem *addr, unsigned offset)
 {
u8 data =  __raw_readb(addr + offset);
 
@@ -260,7 +260,7 @@ static void musb_default_writeb(void __iomem *addr, 
unsigned offset, u8 data)
__raw_writeb(data, addr + offset);
 }
 
-static u16 musb_default_readw(const void __iomem *addr, unsigned offset)
+static u16 musb_default_readw(void __iomem *addr, unsigned offset)
 {
u16 data = __raw_readw(addr + offset);
 
@@ -364,19 +364,19 @@ static void musb_default_read_fifo(struct musb_hw_ep 
*hw_ep, u16 len, u8 *dst)
 /*
  * Old style IO functions
  */
-u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readb);
 
 void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
 EXPORT_SYMBOL_GPL(musb_writeb);
 
-u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readw);
 
 void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
 EXPORT_SYMBOL_GPL(musb_writew);
 
-u32 musb_readl(const void __iomem *addr, unsigned offset)
+u32 musb_readl(void __iomem *addr, unsigned offset)
 {
u32 data = __raw_readl(addr + offset);
 
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7..daf5422 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -161,9 +161,9 @@ struct musb_platform_ops {
u16 fifo_mode;
u32 (*fifo_offset)(u8 epnum);
u32 (*busctl_offset)(u8 epnum, u16 offset);
-   u8  (*readb)(const void __iomem *addr, unsigned offset);
+   u8  (*readb)(void __iomem *addr, unsigned offset);
void(*writeb)(void __iomem *addr, unsigned offset, u8 data);
-   u16 (*readw)(const void __iomem *addr, unsigned offset);
+   u16 (*readw)(void __iomem *addr, unsigned offset);
void(*writew)(void __iomem *addr, unsigned offset, u16 data);
void(*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void(*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
index 8058a58..34ea2a4 100644
--- a/drivers/usb/musb/musb_io.h
+++ b/drivers/usb/musb/musb_io.h
@@ -33,11 +33,11 @@ struct musb_io {
 };
 
 /* Do not add new entries here, add them the struct musb_io instead */
-extern u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+extern u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 extern void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
-extern u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+extern u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 extern void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
-extern u32 musb_readl(const void __iomem *addr, unsigned offset);
+extern u32 musb_readl(void __iomem *addr, unsigned offset);
 extern void musb_writel(void __iomem *addr, unsigned offset, u32 data);
 
 #endif
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 832a41f..2c1bbaa 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -407,7 +407,7 @@ static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
return SUNXI_MUSB_TXFUNCADDR + offset;
 }
 
-static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset)
+static u8 sunxi_musb_readb(void __iomem *addr, unsigned offset)
 {
struct sunxi_glue *glue;
 
@@ -520,7 +520,7 @@ static void sunxi_musb_writeb(void __iomem *addr, unsigned 
offset, u8 data)
(int)(addr - sunxi_musb->mregs));
 }
 
-static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset)
+static u16 sunxi_musb_readw(void __iomem *addr, unsigned offset)
 {
if (addr == sunxi_musb->mregs) {
/* generic control or fifo control reg access */
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 3945328..cfb94f9 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -142,7 +142,7 @@ static void tusb_ep_select(void __iomem *mbase, u8 epnum)
 /*
  * TUSB6010 doesn't allow 8-bit access; 16-bit acces

[PATCH v3 2/4] arm: dts: mt2701: Add usb2 device nodes

2019-01-16 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index be0edb3..2635911 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -60,6 +61,20 @@
>;
default-brightness-level = <9>;
};
+
+   extcon_usb: extcon_iddig {
+   compatible = "linux,extcon-usb-gpio";
+   id-gpio = <&pio 44 GPIO_ACTIVE_HIGH>;
+   };
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -229,3 +244,9 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 180377e..a6b1434 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -670,6 +670,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH v3 0/4] Add MediaTek MUSB Controller Driver

2019-01-16 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v3:
changes of driver suggested by Bin:
1. Add a new patch for musb_readb/w/l() to remove const attribute 
2. Use is_out as function parameter in set_toggle/get_toggle() hooks
3. Remove 'u8/u16 data' parameter in clearb/w() hooks
4. Remove musb_default_clearb/w()
5. Replace musb_readb/w() with musb_clearb/w() to clear pending interrupts 
6. Add comments to clearb/w() hooks
7. Replace musb_save_toggle() with musb->io.get_toggle()
8. Replace musb_set_toggle() with musb->io.set_toggle()

changes in v2:
changes of dt-bindings suggested by Rob:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (4):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Delete the const attribute of addr parameter in readb/w/l
hooks
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  43 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   8 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 624 +
 drivers/usb/musb/musb_core.c   |  74 ++-
 drivers/usb/musb/musb_core.h   |  13 +-
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  46 +-
 drivers/usb/musb/musb_io.h |  12 +-
 drivers/usb/musb/musbhsdma.c   |  57 +-
 drivers/usb/musb/sunxi.c   |   4 +-
 drivers/usb/musb/tusb6010.c|   2 +-
 14 files changed, 876 insertions(+), 71 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH v3 4/4] usb: musb: Add support for MediaTek musb controller

2019-01-16 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
 drivers/usb/musb/Kconfig |   8 +-
 drivers/usb/musb/Makefile|   1 +
 drivers/usb/musb/mediatek.c  | 624 +++
 drivers/usb/musb/musb_core.c |  64 -
 drivers/usb/musb/musb_core.h |   9 +
 drivers/usb/musb/musb_dma.h  |   9 +
 drivers/usb/musb/musb_host.c |  46 +---
 drivers/usb/musb/musb_io.h   |   6 +
 drivers/usb/musb/musbhsdma.c |  57 ++--
 9 files changed, 766 insertions(+), 58 deletions(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index ad08895..b72b7c1 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -115,6 +115,12 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -141,7 +147,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..65cafa6
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,624 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+enum mtk_vbus_id_state {
+   MTK_ID_FLOAT = 1,
+   MTK_ID_GROUND,
+   MTK_VBUS_OFF,
+   MTK_VBUS_VALID,
+};
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   struct regulator *vbus;
+   struct extcon_dev *edev;
+   struct notifier_block vbus_nb;
+   struct notifier_block id_nb;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+   return PTR_ERR(glue->univpll);
+   }
+
+   return 0;
+}
+
+static int mtk_musb_clks_enable(struct mtk_glue *glue)
+{
+   int ret;
+
+   ret = clk_prepare_enable(glue->main);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable main clock\n");
+   goto err_main_clk;
+   }
+
+   ret = clk_prepare_enable(glue->mcu);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable mcu clock\n");
+   goto err_mcu_clk;
+   }
+
+   ret = clk_prepare_enable(glue->univpll);
+   if (ret) {
+   dev_err(glue->dev, "failed to enabl

[PATCH v2 3/4] usb: musb: Extract set toggle as a separate interface

2019-01-14 Thread min.guo
From: Min Guo 

Add a common interface for set data toggle

Signed-off-by: Min Guo 
---
 drivers/usb/musb/musb_host.c | 37 +++--
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index b59ce9a..16d0ba4 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -306,6 +306,25 @@ static inline void musb_save_toggle(struct musb_qh *qh, 
int is_in,
usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
 }
 
+static inline u16 musb_set_toggle(struct musb_qh *qh, int is_in,
+   struct urb *urb)
+{
+   u16 csr = 0;
+   u16 toggle = 0;
+
+   toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in);
+
+   if (is_in)
+   csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
+   | MUSB_RXCSR_H_DATATOGGLE) : 0;
+   else
+   csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
+   | MUSB_TXCSR_H_DATATOGGLE)
+   : MUSB_TXCSR_CLRDATATOG;
+
+   return csr;
+}
+
 /*
  * Advance this hardware endpoint's queue, completing the specified URB and
  * advancing to either the next URB queued to that qh, or else invalidating
@@ -772,13 +791,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
);
csr |= MUSB_TXCSR_MODE;
 
-   if (!hw_ep->tx_double_buffered) {
-   if (usb_gettoggle(urb->dev, qh->epnum, 1))
-   csr |= MUSB_TXCSR_H_WR_DATATOGGLE
-   | MUSB_TXCSR_H_DATATOGGLE;
-   else
-   csr |= MUSB_TXCSR_CLRDATATOG;
-   }
+   if (!hw_ep->tx_double_buffered)
+   csr |= musb_set_toggle(qh, !is_out, urb);
 
musb_writew(epio, MUSB_TXCSR, csr);
/* REVISIT may need to clear FLUSHFIFO ... */
@@ -860,17 +874,12 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
 
/* IN/receive */
} else {
-   u16 csr;
+   u16 csr = 0;
 
if (hw_ep->rx_reinit) {
musb_rx_reinit(musb, qh, epnum);
+   csr |= musb_set_toggle(qh, !is_out, urb);
 
-   /* init new state: toggle and NYET, maybe DMA later */
-   if (usb_gettoggle(urb->dev, qh->epnum, 0))
-   csr = MUSB_RXCSR_H_WR_DATATOGGLE
-   | MUSB_RXCSR_H_DATATOGGLE;
-   else
-   csr = 0;
if (qh->type == USB_ENDPOINT_XFER_INT)
csr |= MUSB_RXCSR_DISNYET;
 
-- 
1.9.1



[PATCH v2 0/4] Add MediaTek MUSB Controller Driver

2019-01-14 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v2:
changes of dt-bindings suggested by Rob and Bin:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (4):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Extract set toggle as a separate interface
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  43 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   8 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 617 +
 drivers/usb/musb/musb_core.c   |  69 +++
 drivers/usb/musb/musb_core.h   |   9 +
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  35 +-
 drivers/usb/musb/musb_io.h |   6 +
 drivers/usb/musb/musbhsdma.c   |  55 +-
 12 files changed, 868 insertions(+), 38 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH v2 4/4] usb: musb: Add support for MediaTek musb controller

2019-01-14 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
 drivers/usb/musb/Kconfig |   8 +-
 drivers/usb/musb/Makefile|   1 +
 drivers/usb/musb/mediatek.c  | 617 +++
 drivers/usb/musb/musb_core.c |  69 +
 drivers/usb/musb/musb_core.h |   9 +
 drivers/usb/musb/musb_dma.h  |   9 +
 drivers/usb/musb/musb_host.c |  26 +-
 drivers/usb/musb/musb_io.h   |   6 +
 drivers/usb/musb/musbhsdma.c |  55 ++--
 9 files changed, 762 insertions(+), 38 deletions(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index ad08895..b72b7c1 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -115,6 +115,12 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -141,7 +147,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..7221989
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,617 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+enum mtk_vbus_id_state {
+   MTK_ID_FLOAT = 1,
+   MTK_ID_GROUND,
+   MTK_VBUS_OFF,
+   MTK_VBUS_VALID,
+};
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   struct regulator *vbus;
+   struct extcon_dev *edev;
+   struct notifier_block vbus_nb;
+   struct notifier_block id_nb;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+   return PTR_ERR(glue->univpll);
+   }
+
+   return 0;
+}
+
+static int mtk_musb_clks_enable(struct mtk_glue *glue)
+{
+   int ret;
+
+   ret = clk_prepare_enable(glue->main);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable main clock\n");
+   goto err_main_clk;
+   }
+
+   ret = clk_prepare_enable(glue->mcu);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable mcu clock\n");
+   goto err_mcu_clk;
+   }
+
+   ret = clk_prepare_enable(glue->univpll);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable univpll 

[PATCH v2 1/4] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-01-14 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 43 ++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..3e3f671
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,43 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+   the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+   refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+   each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+   for clocks of controller
+
+Optional properties:
+ - extcon : external connector for VBUS and IDPIN changes detection,
+   needed when supports dual-role mode.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+   dual-role mode.
+ - power-domains   : a phandle to USB power domain node to control USB's
+   MTCMOS
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+};
-- 
1.9.1



[PATCH v2 2/4] arm: dts: mt2701: Add usb2 device nodes

2019-01-14 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index be0edb3..2635911 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -60,6 +61,20 @@
>;
default-brightness-level = <9>;
};
+
+   extcon_usb: extcon_iddig {
+   compatible = "linux,extcon-usb-gpio";
+   id-gpio = <&pio 44 GPIO_ACTIVE_HIGH>;
+   };
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -229,3 +244,9 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 180377e..a6b1434 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -670,6 +670,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH v4 1/6] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-01-21 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
---
changes in v4:
suggested by Sergei:
1. String alignment

changes in v3:
1. no changes

changes in v2:
suggested by Bin:
1. Modify DRC to DRD
suggested by Rob:
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 43 ++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..4305770
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,43 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+ the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+ refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+ each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+ for clocks of controller
+
+Optional properties:
+ - extcon  : external connector for VBUS and ID pin changes detection,
+ needed when supports dual-role mode
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+ dual-role mode
+ - power-domains   : a phandle to USB power domain node to control USB's
+ MTCMOS
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+};
-- 
1.9.1



[PATCH v4 6/6] usb: musb: Add support for MediaTek musb controller

2019-01-21 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
changes in v4:
1. no changes

changes in v3:
suggested by Bin:
1. Remove 'u8/u16 data' parameter in clearb/w() hooks
2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status

changes in v2:
suggested by Bin:
1. Add summarize of MediaTek musb controller differences in the commit log
2. Add "|| COMPILE_TEST" in Kconfig
3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
4. Replace musb_readl() with musb_readw() to read 16bit toggle register
---
 drivers/usb/musb/Kconfig|   8 +-
 drivers/usb/musb/Makefile   |   1 +
 drivers/usb/musb/mediatek.c | 624 
 3 files changed, 632 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index ad08895..b72b7c1 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -115,6 +115,12 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -141,7 +147,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..65cafa6
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,624 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+enum mtk_vbus_id_state {
+   MTK_ID_FLOAT = 1,
+   MTK_ID_GROUND,
+   MTK_VBUS_OFF,
+   MTK_VBUS_VALID,
+};
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   struct regulator *vbus;
+   struct extcon_dev *edev;
+   struct notifier_block vbus_nb;
+   struct notifier_block id_nb;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+   return PTR_ERR(glue->univpll);
+   }
+
+   return 0;
+}
+
+static int mtk_musb_clks_enable(struct mtk_glue *glue)
+{
+   int ret;
+
+   ret = clk_prepare_enable(glue->main);
+   if (ret) {
+   dev_err(glue->dev, "failed to enable main clock\n");
+   goto err_main_clk;
+   }
+
+   ret = clk_prepare_enable(glue->mcu);
+  

[PATCH v4 5/6] usb: musb: Add musb_clearb/w() interface

2019-01-21 Thread min.guo
From: Min Guo 

Delete the const attribute of addr parameter in readb/w/l hooks, these
changes are for implementing clearing W1C registers.
Replace musb_readb/w with musb_clearb/w to clear the interrupt status.

Signed-off-by: Min Guo 
---
new patch based on v3:
---
 drivers/usb/musb/musb_core.c | 32 +++-
 drivers/usb/musb/musb_core.h |  8 ++--
 drivers/usb/musb/musb_io.h   |  8 +---
 drivers/usb/musb/musbhsdma.c |  3 +++
 drivers/usb/musb/sunxi.c |  4 ++--
 drivers/usb/musb/tusb6010.c  |  2 +-
 6 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 2fe5225..5ef8848 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -246,7 +246,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset)
return 0x80 + (0x08 * epnum) + offset;
 }
 
-static u8 musb_default_readb(const void __iomem *addr, unsigned offset)
+static u8 musb_default_readb(void __iomem *addr, unsigned offset)
 {
u8 data =  __raw_readb(addr + offset);
 
@@ -260,7 +260,7 @@ static void musb_default_writeb(void __iomem *addr, 
unsigned offset, u8 data)
__raw_writeb(data, addr + offset);
 }
 
-static u16 musb_default_readw(const void __iomem *addr, unsigned offset)
+static u16 musb_default_readw(void __iomem *addr, unsigned offset)
 {
u16 data = __raw_readw(addr + offset);
 
@@ -396,19 +396,25 @@ static void musb_default_read_fifo(struct musb_hw_ep 
*hw_ep, u16 len, u8 *dst)
 /*
  * Old style IO functions
  */
-u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readb);
 
 void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
 EXPORT_SYMBOL_GPL(musb_writeb);
 
-u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+u8 (*musb_clearb)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearb);
+
+u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readw);
 
 void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
 EXPORT_SYMBOL_GPL(musb_writew);
 
-u32 musb_readl(const void __iomem *addr, unsigned offset)
+u16 (*musb_clearw)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearw);
+
+u32 musb_readl(void __iomem *addr, unsigned offset)
 {
u32 data = __raw_readl(addr + offset);
 
@@ -1047,7 +1053,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 
int_usb,
 static void musb_disable_interrupts(struct musb *musb)
 {
void __iomem*mbase = musb->mregs;
-   u16 temp;
 
/* disable interrupts */
musb_writeb(mbase, MUSB_INTRUSBE, 0);
@@ -1057,9 +1062,9 @@ static void musb_disable_interrupts(struct musb *musb)
musb_writew(mbase, MUSB_INTRRXE, 0);
 
/*  flush pending interrupts */
-   temp = musb_readb(mbase, MUSB_INTRUSB);
-   temp = musb_readw(mbase, MUSB_INTRTX);
-   temp = musb_readw(mbase, MUSB_INTRRX);
+   musb_clearb(mbase, MUSB_INTRUSB);
+   musb_clearw(mbase, MUSB_INTRTX);
+   musb_clearw(mbase, MUSB_INTRRX);
 }
 
 static void musb_enable_interrupts(struct musb *musb)
@@ -2284,10 +2289,19 @@ static void musb_deassert_reset(struct work_struct 
*work)
musb_readb = musb->ops->readb;
if (musb->ops->writeb)
musb_writeb = musb->ops->writeb;
+   if (musb->ops->clearb)
+   musb_clearb = musb->ops->clearb;
+   else
+   musb_clearb = musb_readb;
+
if (musb->ops->readw)
musb_readw = musb->ops->readw;
if (musb->ops->writew)
musb_writew = musb->ops->writew;
+   if (musb->ops->clearw)
+   musb_clearw = musb->ops->clearw;
+   else
+   musb_clearw = musb_readw;
 
 #ifndef CONFIG_MUSB_PIO_ONLY
if (!musb->ops->dma_init || !musb->ops->dma_exit) {
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 9f5a69c..0d9a35f 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -120,8 +120,10 @@ enum musb_g_ep0_state {
  * @fifo_offset: returns the fifo offset
  * @readb: read 8 bits
  * @writeb:write 8 bits
+ * @clearb:could be clear-on-readb or W1C
  * @readw: read 16 bits
  * @writew:write 16 bits
+ * @clearw:could be clear-on-readw or W1C
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
  * @get_toggle:platform specific get toggle function
@@ -164,10 +166,12 @@ struct musb_platform_ops {
u16 fifo_mode;
u32 (*fifo_offset)(u8 epnum);
u32 (*busctl_offset)(u8 epnum, u16 offset);
-   u8  (*readb)(const void __iomem *addr, unsigned offset);
+   u8  (*readb)(void __iomem *addr, unsigned offset);
void(*writeb)(void __iomem *addr, unsigned offset, u8 data);
-   u16 (*readw)(const void __iomem *addr, unsigned o

[PATCH v4 3/6] usb: musb: Add get/set toggle hooks

2019-01-21 Thread min.guo
From: Min Guo 

Add get/set toggle hooks in struct musb_io and struct musb_platform_ops
for special platform; remove function musb_save_toggle, use the set/get
callback to handle toggle.

Signed-off-by: Min Guo 
---
new patch based on v3:
---
 drivers/usb/musb/musb_core.c | 42 
 drivers/usb/musb/musb_core.h |  5 +
 drivers/usb/musb/musb_host.c | 46 ++--
 drivers/usb/musb/musb_io.h   |  4 
 4 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index b7d5627..2fe5225 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -274,6 +274,38 @@ static void musb_default_writew(void __iomem *addr, 
unsigned offset, u16 data)
__raw_writew(data, addr + offset);
 }
 
+static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out)
+{
+   void __iomem *epio = qh->hw_ep->regs;
+   u16 csr;
+
+   if (is_out)
+   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+   else
+   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+
+   return csr;
+}
+
+static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out,
+  struct urb *urb)
+{
+   u16 csr;
+   u16 toggle;
+
+   toggle = usb_gettoggle(urb->dev, qh->epnum, is_out);
+
+   if (is_out)
+   csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
+   | MUSB_TXCSR_H_DATATOGGLE)
+   : MUSB_TXCSR_CLRDATATOG;
+   else
+   csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
+   | MUSB_RXCSR_H_DATATOGGLE) : 0;
+
+   return csr;
+}
+
 /*
  * Load an endpoint's FIFO
  */
@@ -2277,6 +2309,16 @@ static void musb_deassert_reset(struct work_struct *work)
else
musb->io.write_fifo = musb_default_write_fifo;
 
+   if (musb->ops->get_toggle)
+   musb->io.get_toggle = musb->ops->get_toggle;
+   else
+   musb->io.get_toggle = musb_default_get_toggle;
+
+   if (musb->ops->set_toggle)
+   musb->io.set_toggle = musb->ops->set_toggle;
+   else
+   musb->io.set_toggle = musb_default_set_toggle;
+
if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7..9f5a69c 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -27,6 +27,7 @@
 struct musb;
 struct musb_hw_ep;
 struct musb_ep;
+struct musb_qh;
 
 /* Helper defines for struct musb->hwvers */
 #define MUSB_HWVERS_MAJOR(x)   ((x >> 10) & 0x1f)
@@ -123,6 +124,8 @@ enum musb_g_ep0_state {
  * @writew:write 16 bits
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
+ * @get_toggle:platform specific get toggle function
+ * @set_toggle:platform specific set toggle function
  * @dma_init:  platform specific dma init function
  * @dma_exit:  platform specific dma exit function
  * @init:  turns on clocks, sets up platform-specific registers, etc
@@ -167,6 +170,8 @@ struct musb_platform_ops {
void(*writew)(void __iomem *addr, unsigned offset, u16 data);
void(*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void(*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
+   u16 (*get_toggle)(struct musb_qh *qh, int is_out);
+   u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
struct dma_controller *
(*dma_init) (struct musb *musb, void __iomem *base);
void(*dma_exit)(struct dma_controller *c);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index b59ce9a..b97fbf9 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -286,26 +286,6 @@ static void musb_giveback(struct musb *musb, struct urb 
*urb, int status)
spin_lock(&musb->lock);
 }
 
-/* For bulk/interrupt endpoints only */
-static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
-   struct urb *urb)
-{
-   void __iomem*epio = qh->hw_ep->regs;
-   u16 csr;
-
-   /*
-* FIXME: the current Mentor DMA code seems to have
-* problems getting toggle correct.
-*/
-
-   if (is_in)
-   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
-   else
-   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
-
-   usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
-}
-
 /*
  * Advance this hardware endpoint's queue, completing the specified URB and
  * advancing to either the next URB queued to that qh, or else invalidating
@@ -320,6 +300,7 @@ static v

[PATCH v4 0/6] Add MediaTek MUSB Controller Driver

2019-01-21 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v4:
changes of dt-bindings suggested by Sergei:
1. String alignment
changes of driver suggested by Tony and Bin:
1. Add a new patch for set/get_toggle()
2. Add a new patch for noirq type of dma
3. Add a new patch musb_clearb/w()
4. Abondon patch "usb: musb: Delete the const attribute of addr parameter in 
readb/w/l hooks"

changes in v3:
changes of driver suggested by Bin:
1. Add a new patch for musb_readb/w/l() to remove const attribute 
2. Use is_out as function parameter in set_toggle/get_toggle() hooks
3. Remove 'u8/u16 data' parameter in clearb/w() hooks
4. Remove musb_default_clearb/w()
5. Replace musb_readb/w() with musb_clearb/w() to clear pending interrupts 
6. Add comments to clearb/w() hooks
7. Replace musb_save_toggle() with musb->io.get_toggle()
8. Replace musb_set_toggle() with musb->io.set_toggle()

changes in v2:
changes of dt-bindings suggested by Rob and Bin:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (6):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Add get/set toggle hooks
  usb: musb: Add noirq type of dma create interface
  usb: musb: Add musb_clearb/w() interface
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  43 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   8 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 624 +
 drivers/usb/musb/musb_core.c   |  74 ++-
 drivers/usb/musb/musb_core.h   |  13 +-
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  46 +-
 drivers/usb/musb/musb_io.h |  12 +-
 drivers/usb/musb/musbhsdma.c   |  57 +-
 drivers/usb/musb/sunxi.c   |   4 +-
 drivers/usb/musb/tusb6010.c|   2 +-
 14 files changed, 876 insertions(+), 71 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH v4 2/6] arm: dts: mt2701: Add usb2 device nodes

2019-01-21 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
changes in v4:
1. no changes

changes in v3:
1. no changes

changes in v2:
1. Remove phy-names
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index be0edb3..2635911 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -60,6 +61,20 @@
>;
default-brightness-level = <9>;
};
+
+   extcon_usb: extcon_iddig {
+   compatible = "linux,extcon-usb-gpio";
+   id-gpio = <&pio 44 GPIO_ACTIVE_HIGH>;
+   };
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -229,3 +244,9 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   vbus-supply = <&usb_vbus>;
+   extcon = <&extcon_usb>;
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 180377e..a6b1434 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -670,6 +670,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH v4 4/6] usb: musb: Add noirq type of dma create interface

2019-01-21 Thread min.guo
From: Min Guo 

Add noirq type of dma create interface for platform which do not
have dedicated DMA interrupt line, move musbhsdma macro definition
to musb_dma.h

Signed-off-by: Min Guo 
---
new patch based on v3:
---
 drivers/usb/musb/musb_dma.h  |  9 
 drivers/usb/musb/musbhsdma.c | 54 ++--
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 8f60271..05103ea 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -35,6 +35,12 @@
  *whether shared with the Inventra core or separate.
  */
 
+#define MUSB_HSDMA_BASE0x200
+#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL 0x4
+#define MUSB_HSDMA_ADDRESS 0x8
+#define MUSB_HSDMA_COUNT   0xc
+
 #defineDMA_ADDR_INVALID(~(dma_addr_t)0)
 
 #ifdef CONFIG_MUSB_PIO_ONLY
@@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct 
dma_controller *d) { }
 extern struct dma_controller *
 musbhs_dma_controller_create(struct musb *musb, void __iomem *base);
 extern void musbhs_dma_controller_destroy(struct dma_controller *c);
+extern struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base);
+extern irqreturn_t dma_controller_irq(int irq, void *private_data);
 
 extern struct dma_controller *
 tusb_dma_controller_create(struct musb *musb, void __iomem *base);
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index a688f7f..b2394a7 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -10,12 +10,7 @@
 #include 
 #include 
 #include "musb_core.h"
-
-#define MUSB_HSDMA_BASE0x200
-#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL 0x4
-#define MUSB_HSDMA_ADDRESS 0x8
-#define MUSB_HSDMA_COUNT   0xc
+#include "musb_dma.h"
 
 #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)  \
(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
@@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel)
return 0;
 }
 
-static irqreturn_t dma_controller_irq(int irq, void *private_data)
+irqreturn_t dma_controller_irq(int irq, void *private_data)
 {
struct musb_dma_controller *controller = private_data;
struct musb *musb = controller->private_data;
@@ -382,6 +377,7 @@ static irqreturn_t dma_controller_irq(int irq, void 
*private_data)
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
 }
+EXPORT_SYMBOL_GPL(dma_controller_irq);
 
 void musbhs_dma_controller_destroy(struct dma_controller *c)
 {
@@ -397,18 +393,10 @@ void musbhs_dma_controller_destroy(struct dma_controller 
*c)
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy);
 
-struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
-   void __iomem *base)
+static struct musb_dma_controller *
+dma_controller_alloc(struct musb *musb, void __iomem *base)
 {
struct musb_dma_controller *controller;
-   struct device *dev = musb->controller;
-   struct platform_device *pdev = to_platform_device(dev);
-   int irq = platform_get_irq_byname(pdev, "dma");
-
-   if (irq <= 0) {
-   dev_err(dev, "No DMA interrupt line!\n");
-   return NULL;
-   }
 
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
@@ -422,6 +410,25 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
controller->controller.channel_release = dma_channel_release;
controller->controller.channel_program = dma_channel_program;
controller->controller.channel_abort = dma_channel_abort;
+   return controller;
+}
+
+struct dma_controller *
+musbhs_dma_controller_create(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+   struct device *dev = musb->controller;
+   struct platform_device *pdev = to_platform_device(dev);
+   int irq = platform_get_irq_byname(pdev, "dma");
+
+   if (irq <= 0) {
+   dev_err(dev, "No DMA interrupt line!\n");
+   return NULL;
+   }
+
+   controller = dma_controller_alloc(musb, base);
+   if (!controller)
+   return NULL;
 
if (request_irq(irq, dma_controller_irq, 0,
dev_name(musb->controller), &controller->controller)) {
@@ -436,3 +443,16 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
return &controller->controller;
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_create);
+
+struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+
+   controller = dma_controller_alloc(musb, ba

[PATCH v5 1/6] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-02-18 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
---
changes in v5:
suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node

changes in v4:
suggested by Sergei:
1. String alignment

changes in v3:
1. no changes

changes in v2:
suggested by Bin:
1. Modify DRC to DRD
suggested by Rob:
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 54 ++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..0632e6e
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,54 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be one of:
+ "mediatek,mt-2701"
+ ...
+ followed by "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+ the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+ refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+ each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+ for clocks of controller
+
+Optional properties:
+ - power-domains   : a phandle to USB power domain node to control USB's
+ MTCMOS
+
+Required child nodes:
+ usb connector node as defined in bindings/connector/usb-connector.txt
+ - extcon  : for VBUS and ID pin changes detection, needed when
+ supports dual-role mode
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+ dual-role mode
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   usb_con: connector{
+   compatible = "usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   extcon = <&extcon_usb>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
-- 
1.9.1



[PATCH v5 0/6] Add MediaTek MUSB Controller Driver

2019-02-18 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v5:
changes of dt-bindings suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node
changes of DTS:
1. Add usb connector child node
changes of driver suggested by Bin:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts
2. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
3. Make musb_clearb/w() return the value of musb_readb/w()

changes in v4:
changes of dt-bindings suggested by Sergei:
1. String alignment
changes of driver suggested by Tony and Bin:
1. Add a new patch for set/get_toggle()
2. Add a new patch for noirq type of dma
3. Add a new patch musb_clearb/w()
4. Abondon patch "usb: musb: Delete the const attribute of addr parameter in 
readb/w/l hooks"

changes in v3:
changes of driver suggested by Bin:
1. Add a new patch for musb_readb/w/l() to remove const attribute 
2. Use is_out as function parameter in set_toggle/get_toggle() hooks
3. Remove 'u8/u16 data' parameter in clearb/w() hooks
4. Remove musb_default_clearb/w()
5. Replace musb_readb/w() with musb_clearb/w() to clear pending interrupts 
6. Add comments to clearb/w() hooks
7. Replace musb_save_toggle() with musb->io.get_toggle()
8. Replace musb_set_toggle() with musb->io.set_toggle()

changes in v2:
changes of dt-bindings suggested by Rob and Bin:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (6):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Add get/set toggle hooks
  usb: musb: Add noirq type of dma create interface
  usb: musb: Add musb_clearb/w() interface
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  54 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  26 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   8 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 629 +
 drivers/usb/musb/musb_core.c   |  74 ++-
 drivers/usb/musb/musb_core.h   |  13 +-
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  46 +-
 drivers/usb/musb/musb_io.h |  12 +-
 drivers/usb/musb/musbhsdma.c   |  56 +-
 drivers/usb/musb/sunxi.c   |   4 +-
 drivers/usb/musb/tusb6010.c|   2 +-
 14 files changed, 895 insertions(+), 72 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH v5 6/6] usb: musb: Add support for MediaTek musb controller

2019-02-18 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
changes in v5:
1. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
2. Make musb_clearb/w() return the value of musb_readb/w()
3. Add driver to get child nodes of usb connector and extcon device

changes in v4:
1. no changes

changes in v3:
suggested by Bin:
1. Remove 'u8/u16 data' parameter in clearb/w() hooks
2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status

changes in v2:
suggested by Bin:
1. Add summarize of MediaTek musb controller differences in the commit log
2. Add "|| COMPILE_TEST" in Kconfig
3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
4. Replace musb_readl() with musb_readw() to read 16bit toggle register
---
 drivers/usb/musb/Kconfig|   8 +-
 drivers/usb/musb/Makefile   |   1 +
 drivers/usb/musb/mediatek.c | 629 
 3 files changed, 637 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index ad08895..b72b7c1 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -115,6 +115,12 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -141,7 +147,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..946b453
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,629 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+enum mtk_vbus_id_state {
+   MTK_ID_FLOAT = 1,
+   MTK_ID_GROUND,
+   MTK_VBUS_OFF,
+   MTK_VBUS_VALID,
+};
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   struct regulator *vbus;
+   struct extcon_dev *edev;
+   struct notifier_block vbus_nb;
+   struct notifier_block id_nb;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+   return PTR_ERR(glue->univpll);
+   }
+
+   return 0;
+}
+
+static int mtk_musb_clks_enable(struct mtk_glue *glue)
+{
+   int ret;
+
+

[PATCH v5 5/6] usb: musb: Add musb_clearb/w() interface

2019-02-18 Thread min.guo
From: Min Guo 

Delete the const attribute of addr parameter in readb/w/l hooks, these
changes are for implementing clearing W1C registers.
Replace musb_readb/w with musb_clearb/w to clear the interrupt status.

Signed-off-by: Min Guo 
---
changes in v5:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 32 +++-
 drivers/usb/musb/musb_core.h |  8 ++--
 drivers/usb/musb/musb_io.h   |  8 +---
 drivers/usb/musb/musbhsdma.c |  2 +-
 drivers/usb/musb/sunxi.c |  4 ++--
 drivers/usb/musb/tusb6010.c  |  2 +-
 6 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 2fe5225..5ef8848 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -246,7 +246,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset)
return 0x80 + (0x08 * epnum) + offset;
 }
 
-static u8 musb_default_readb(const void __iomem *addr, unsigned offset)
+static u8 musb_default_readb(void __iomem *addr, unsigned offset)
 {
u8 data =  __raw_readb(addr + offset);
 
@@ -260,7 +260,7 @@ static void musb_default_writeb(void __iomem *addr, 
unsigned offset, u8 data)
__raw_writeb(data, addr + offset);
 }
 
-static u16 musb_default_readw(const void __iomem *addr, unsigned offset)
+static u16 musb_default_readw(void __iomem *addr, unsigned offset)
 {
u16 data = __raw_readw(addr + offset);
 
@@ -396,19 +396,25 @@ static void musb_default_read_fifo(struct musb_hw_ep 
*hw_ep, u16 len, u8 *dst)
 /*
  * Old style IO functions
  */
-u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readb);
 
 void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
 EXPORT_SYMBOL_GPL(musb_writeb);
 
-u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+u8 (*musb_clearb)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearb);
+
+u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readw);
 
 void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
 EXPORT_SYMBOL_GPL(musb_writew);
 
-u32 musb_readl(const void __iomem *addr, unsigned offset)
+u16 (*musb_clearw)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearw);
+
+u32 musb_readl(void __iomem *addr, unsigned offset)
 {
u32 data = __raw_readl(addr + offset);
 
@@ -1047,7 +1053,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 
int_usb,
 static void musb_disable_interrupts(struct musb *musb)
 {
void __iomem*mbase = musb->mregs;
-   u16 temp;
 
/* disable interrupts */
musb_writeb(mbase, MUSB_INTRUSBE, 0);
@@ -1057,9 +1062,9 @@ static void musb_disable_interrupts(struct musb *musb)
musb_writew(mbase, MUSB_INTRRXE, 0);
 
/*  flush pending interrupts */
-   temp = musb_readb(mbase, MUSB_INTRUSB);
-   temp = musb_readw(mbase, MUSB_INTRTX);
-   temp = musb_readw(mbase, MUSB_INTRRX);
+   musb_clearb(mbase, MUSB_INTRUSB);
+   musb_clearw(mbase, MUSB_INTRTX);
+   musb_clearw(mbase, MUSB_INTRRX);
 }
 
 static void musb_enable_interrupts(struct musb *musb)
@@ -2284,10 +2289,19 @@ static void musb_deassert_reset(struct work_struct 
*work)
musb_readb = musb->ops->readb;
if (musb->ops->writeb)
musb_writeb = musb->ops->writeb;
+   if (musb->ops->clearb)
+   musb_clearb = musb->ops->clearb;
+   else
+   musb_clearb = musb_readb;
+
if (musb->ops->readw)
musb_readw = musb->ops->readw;
if (musb->ops->writew)
musb_writew = musb->ops->writew;
+   if (musb->ops->clearw)
+   musb_clearw = musb->ops->clearw;
+   else
+   musb_clearw = musb_readw;
 
 #ifndef CONFIG_MUSB_PIO_ONLY
if (!musb->ops->dma_init || !musb->ops->dma_exit) {
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 9f5a69c..0d9a35f 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -120,8 +120,10 @@ enum musb_g_ep0_state {
  * @fifo_offset: returns the fifo offset
  * @readb: read 8 bits
  * @writeb:write 8 bits
+ * @clearb:could be clear-on-readb or W1C
  * @readw: read 16 bits
  * @writew:write 16 bits
+ * @clearw:could be clear-on-readw or W1C
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
  * @get_toggle:platform specific get toggle function
@@ -164,10 +166,12 @@ struct musb_platform_ops {
u16 fifo_mode;
u32 (*fifo_offset)(u8 epnum);
u32 (*busctl_offset)(u8 epnum, u16 offset);
-   u8  (*readb)(const void __iomem *addr, unsigned offset);
+   u8  (*readb)(void __iomem *addr, unsigned offset);
void(*writeb)(void __iomem *addr

[PATCH v5 4/6] usb: musb: Add noirq type of dma create interface

2019-02-18 Thread min.guo
From: Min Guo 

Add noirq type of dma create interface for platform which do not
have dedicated DMA interrupt line, move musbhsdma macro definition
to musb_dma.h

Signed-off-by: Min Guo 
---
changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_dma.h  |  9 
 drivers/usb/musb/musbhsdma.c | 54 ++--
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 8f60271..05103ea 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -35,6 +35,12 @@
  *whether shared with the Inventra core or separate.
  */
 
+#define MUSB_HSDMA_BASE0x200
+#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL 0x4
+#define MUSB_HSDMA_ADDRESS 0x8
+#define MUSB_HSDMA_COUNT   0xc
+
 #defineDMA_ADDR_INVALID(~(dma_addr_t)0)
 
 #ifdef CONFIG_MUSB_PIO_ONLY
@@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct 
dma_controller *d) { }
 extern struct dma_controller *
 musbhs_dma_controller_create(struct musb *musb, void __iomem *base);
 extern void musbhs_dma_controller_destroy(struct dma_controller *c);
+extern struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base);
+extern irqreturn_t dma_controller_irq(int irq, void *private_data);
 
 extern struct dma_controller *
 tusb_dma_controller_create(struct musb *musb, void __iomem *base);
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index a688f7f..b2394a7 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -10,12 +10,7 @@
 #include 
 #include 
 #include "musb_core.h"
-
-#define MUSB_HSDMA_BASE0x200
-#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL 0x4
-#define MUSB_HSDMA_ADDRESS 0x8
-#define MUSB_HSDMA_COUNT   0xc
+#include "musb_dma.h"
 
 #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)  \
(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
@@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel)
return 0;
 }
 
-static irqreturn_t dma_controller_irq(int irq, void *private_data)
+irqreturn_t dma_controller_irq(int irq, void *private_data)
 {
struct musb_dma_controller *controller = private_data;
struct musb *musb = controller->private_data;
@@ -382,6 +377,7 @@ static irqreturn_t dma_controller_irq(int irq, void 
*private_data)
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
 }
+EXPORT_SYMBOL_GPL(dma_controller_irq);
 
 void musbhs_dma_controller_destroy(struct dma_controller *c)
 {
@@ -397,18 +393,10 @@ void musbhs_dma_controller_destroy(struct dma_controller 
*c)
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy);
 
-struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
-   void __iomem *base)
+static struct musb_dma_controller *
+dma_controller_alloc(struct musb *musb, void __iomem *base)
 {
struct musb_dma_controller *controller;
-   struct device *dev = musb->controller;
-   struct platform_device *pdev = to_platform_device(dev);
-   int irq = platform_get_irq_byname(pdev, "dma");
-
-   if (irq <= 0) {
-   dev_err(dev, "No DMA interrupt line!\n");
-   return NULL;
-   }
 
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
@@ -422,6 +410,25 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
controller->controller.channel_release = dma_channel_release;
controller->controller.channel_program = dma_channel_program;
controller->controller.channel_abort = dma_channel_abort;
+   return controller;
+}
+
+struct dma_controller *
+musbhs_dma_controller_create(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+   struct device *dev = musb->controller;
+   struct platform_device *pdev = to_platform_device(dev);
+   int irq = platform_get_irq_byname(pdev, "dma");
+
+   if (irq <= 0) {
+   dev_err(dev, "No DMA interrupt line!\n");
+   return NULL;
+   }
+
+   controller = dma_controller_alloc(musb, base);
+   if (!controller)
+   return NULL;
 
if (request_irq(irq, dma_controller_irq, 0,
dev_name(musb->controller), &controller->controller)) {
@@ -436,3 +443,16 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
return &controller->controller;
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_create);
+
+struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+
+   controller =

[PATCH v5 2/6] arm: dts: mt2701: Add usb2 device nodes

2019-02-18 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
changes in v5:
1. Add usb connector child node

changes in v4:
1. no changes

changes in v3:
1. no changes

changes in v2:
1. Remove phy-names
---
 arch/arm/boot/dts/mt2701-evb.dts | 26 ++
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 59 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index be0edb3..95458ea 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -60,6 +61,20 @@
>;
default-brightness-level = <9>;
};
+
+   extcon_usb: extcon_iddig {
+   compatible = "linux,extcon-usb-gpio";
+   id-gpio = <&pio 44 GPIO_ACTIVE_HIGH>;
+   };
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -229,3 +244,14 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   status = "okay";
+   usb_con: connector{
+   compatible = "usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   extcon = <&extcon_usb>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 180377e..a6b1434 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -670,6 +670,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH v5 3/6] usb: musb: Add get/set toggle hooks

2019-02-18 Thread min.guo
From: Min Guo 

Add get/set toggle hooks in struct musb_io and struct musb_platform_ops
for special platform; remove function musb_save_toggle, use the set/get
callback to handle toggle.

Signed-off-by: Min Guo 
---
changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 42 
 drivers/usb/musb/musb_core.h |  5 +
 drivers/usb/musb/musb_host.c | 46 ++--
 drivers/usb/musb/musb_io.h   |  4 
 4 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index b7d5627..2fe5225 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -274,6 +274,38 @@ static void musb_default_writew(void __iomem *addr, 
unsigned offset, u16 data)
__raw_writew(data, addr + offset);
 }
 
+static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out)
+{
+   void __iomem *epio = qh->hw_ep->regs;
+   u16 csr;
+
+   if (is_out)
+   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+   else
+   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+
+   return csr;
+}
+
+static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out,
+  struct urb *urb)
+{
+   u16 csr;
+   u16 toggle;
+
+   toggle = usb_gettoggle(urb->dev, qh->epnum, is_out);
+
+   if (is_out)
+   csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
+   | MUSB_TXCSR_H_DATATOGGLE)
+   : MUSB_TXCSR_CLRDATATOG;
+   else
+   csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
+   | MUSB_RXCSR_H_DATATOGGLE) : 0;
+
+   return csr;
+}
+
 /*
  * Load an endpoint's FIFO
  */
@@ -2277,6 +2309,16 @@ static void musb_deassert_reset(struct work_struct *work)
else
musb->io.write_fifo = musb_default_write_fifo;
 
+   if (musb->ops->get_toggle)
+   musb->io.get_toggle = musb->ops->get_toggle;
+   else
+   musb->io.get_toggle = musb_default_get_toggle;
+
+   if (musb->ops->set_toggle)
+   musb->io.set_toggle = musb->ops->set_toggle;
+   else
+   musb->io.set_toggle = musb_default_set_toggle;
+
if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7..9f5a69c 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -27,6 +27,7 @@
 struct musb;
 struct musb_hw_ep;
 struct musb_ep;
+struct musb_qh;
 
 /* Helper defines for struct musb->hwvers */
 #define MUSB_HWVERS_MAJOR(x)   ((x >> 10) & 0x1f)
@@ -123,6 +124,8 @@ enum musb_g_ep0_state {
  * @writew:write 16 bits
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
+ * @get_toggle:platform specific get toggle function
+ * @set_toggle:platform specific set toggle function
  * @dma_init:  platform specific dma init function
  * @dma_exit:  platform specific dma exit function
  * @init:  turns on clocks, sets up platform-specific registers, etc
@@ -167,6 +170,8 @@ struct musb_platform_ops {
void(*writew)(void __iomem *addr, unsigned offset, u16 data);
void(*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void(*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
+   u16 (*get_toggle)(struct musb_qh *qh, int is_out);
+   u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
struct dma_controller *
(*dma_init) (struct musb *musb, void __iomem *base);
void(*dma_exit)(struct dma_controller *c);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index b59ce9a..b97fbf9 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -286,26 +286,6 @@ static void musb_giveback(struct musb *musb, struct urb 
*urb, int status)
spin_lock(&musb->lock);
 }
 
-/* For bulk/interrupt endpoints only */
-static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
-   struct urb *urb)
-{
-   void __iomem*epio = qh->hw_ep->regs;
-   u16 csr;
-
-   /*
-* FIXME: the current Mentor DMA code seems to have
-* problems getting toggle correct.
-*/
-
-   if (is_in)
-   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
-   else
-   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
-
-   usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
-}
-
 /*
  * Advance this hardware endpoint's queue, completing the specified URB and
  * advancing to either the next URB queued to that qh, or else invalidatin

[PATCH] usb: musb: remove unused variable 'devctl'

2020-11-17 Thread min.guo
From: Min Guo 

Remove unused 'devctl' variable to fix compile warnings:

drivers/usb/musb/musbhsdma.c: In function 'dma_controller_irq':
drivers/usb/musb/musbhsdma.c:324:8: warning: variable 'devctl' set
but not used [-Wunused-but-set-variable]

Signed-off-by: Min Guo 
---
 drivers/usb/musb/musbhsdma.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 0aacfc8be5a1..7acd1635850d 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -321,8 +321,6 @@ irqreturn_t dma_controller_irq(int irq, void *private_data)
musb_channel->channel.status =
MUSB_DMA_STATUS_BUS_ABORT;
} else {
-   u8 devctl;
-
addr = musb_read_hsdma_addr(mbase,
bchannel);
channel->actual_len = addr
@@ -336,8 +334,6 @@ irqreturn_t dma_controller_irq(int irq, void *private_data)
< musb_channel->len) ?
"=> reconfig 0" : "=> complete");
 
-   devctl = musb_readb(mbase, MUSB_DEVCTL);
-
channel->status = MUSB_DMA_STATUS_FREE;
 
/* completed */
-- 
2.18.0



[PATCH v6 0/6] Add MediaTek MUSB Controller Driver

2019-06-04 Thread min.guo
From: Min Guo 

These patches introduce the MediaTek MUSB controller driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only modes. This has beed tested on
MT2701 with a variety of devices in host mode and with the 
f_mass gadget driver in peripheral mode, plugging otg cables
in/out a lot of times in all possible imaginable plug orders.

changes in v6:
changes of dt-bindings:
1. Modify usb connector child node
changes of DTS:
1. Modify usb connector child node
changes of driver:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode,
   depends on [1]
3. Remove set vbus function

[1] [v6,09/10] usb: roles: add USB Type-B GPIO connector driver
https://patchwork.kernel.org/patch/10966361/

changes in v5:
changes of dt-bindings suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node
changes of DTS:
1. Add usb connector child node
changes of driver suggested by Bin:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts
2. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
3. Make musb_clearb/w() return the value of musb_readb/w()

changes in v4:
changes of dt-bindings suggested by Sergei:
1. String alignment
changes of driver suggested by Tony and Bin:
1. Add a new patch for set/get_toggle()
2. Add a new patch for noirq type of dma
3. Add a new patch musb_clearb/w()
4. Abondon patch "usb: musb: Delete the const attribute of addr parameter in 
readb/w/l hooks"

changes in v3:
changes of driver suggested by Bin:
1. Add a new patch for musb_readb/w/l() to remove const attribute 
2. Use is_out as function parameter in set_toggle/get_toggle() hooks
3. Remove 'u8/u16 data' parameter in clearb/w() hooks
4. Remove musb_default_clearb/w()
5. Replace musb_readb/w() with musb_clearb/w() to clear pending interrupts 
6. Add comments to clearb/w() hooks
7. Replace musb_save_toggle() with musb->io.get_toggle()
8. Replace musb_set_toggle() with musb->io.set_toggle()

changes in v2:
changes of dt-bindings suggested by Rob and Bin:
1. Modify DRC to DRD
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
dtsi:
1. Remove phy-names
changes of driver suggested by Bin:
1. Add a new patch for musb_set_toggle
2. Add summarize of MediaTek musb controller differences in the commit log
3. Abondon patch "usb: musb: Move musbhsdma macro definition to musb_dma.h"
4. Add "|| COMPILE_TEST" in Kconfig
5. Add musb_clearb() and musb_clearw() hooks
6. Add get_toggle() and set_toggle() hooks
7. Replace musb_readl() with musb_readw() to read 16bit toggle register
8. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
9. Create musbhs_dma_controller_create_noirq()

Min Guo (6):
  dt-bindings: usb: musb: Add support for MediaTek musb controller
  arm: dts: mt2701: Add usb2 device nodes
  usb: musb: Add get/set toggle hooks
  usb: musb: Add noirq type of dma create interface
  usb: musb: Add musb_clearb/w() interface
  usb: musb: Add support for MediaTek musb controller

 .../devicetree/bindings/usb/mediatek,musb.txt  |  55 ++
 arch/arm/boot/dts/mt2701-evb.dts   |  21 +
 arch/arm/boot/dts/mt2701.dtsi  |  33 ++
 drivers/usb/musb/Kconfig   |   9 +-
 drivers/usb/musb/Makefile  |   1 +
 drivers/usb/musb/mediatek.c| 582 +
 drivers/usb/musb/musb_core.c   |  74 ++-
 drivers/usb/musb/musb_core.h   |  13 +-
 drivers/usb/musb/musb_dma.h|   9 +
 drivers/usb/musb/musb_host.c   |  46 +-
 drivers/usb/musb/musb_io.h |  12 +-
 drivers/usb/musb/musbhsdma.c   |  56 +-
 drivers/usb/musb/sunxi.c   |   4 +-
 drivers/usb/musb/tusb6010.c|   2 +-
 14 files changed, 845 insertions(+), 72 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt
 create mode 100644 drivers/usb/musb/mediatek.c

-- 
1.9.1



[PATCH v6 1/6] dt-bindings: usb: musb: Add support for MediaTek musb controller

2019-06-04 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.

Signed-off-by: Min Guo 
---
changes in v6:
1. Modify usb connector child node

changes in v5:
suggested by Rob:
1. Modify compatible as 
- compatible : should be one of:
   "mediatek,mt-2701"
   ...
   followed by "mediatek,mtk-musb"
2. Add usb connector child node

changes in v4:
suggested by Sergei:
1. String alignment

changes in v3:
1. no changes

changes in v2:
suggested by Bin:
1. Modify DRC to DRD
suggested by Rob:
2. Drop the "-musb" in compatible
3. Remove phy-names
4. Add space after comma in clock-names
---
 .../devicetree/bindings/usb/mediatek,musb.txt  | 55 ++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mediatek,musb.txt

diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.txt 
b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
new file mode 100644
index 000..7434299
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mediatek,musb.txt
@@ -0,0 +1,55 @@
+MediaTek musb DRD/OTG controller
+---
+
+Required properties:
+ - compatible  : should be one of:
+ "mediatek,mt-2701"
+ ...
+ followed by "mediatek,mtk-musb"
+ - reg : specifies physical base address and size of
+ the registers
+ - interrupts  : interrupt used by musb controller
+ - interrupt-names : must be "mc"
+ - phys: PHY specifier for the OTG phy
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+ refer to usb/generic.txt
+ - clocks  : a list of phandle + clock-specifier pairs, one for
+ each entry in clock-names
+ - clock-names : must contain "main", "mcu", "univpll"
+ for clocks of controller
+
+Optional properties:
+ - power-domains   : a phandle to USB power domain node to control USB's
+ MTCMOS
+
+Required child nodes:
+ usb connector node as defined in bindings/connector/usb-connector.txt
+Optional properties:
+ - id-gpios: input GPIO for USB ID pin.
+ - vbus-gpios  : input GPIO for USB VBUS pin.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+ dual-role mode
+
+Example:
+
+usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   connector{
+   compatible = "linux,typeb-conn-gpio", "usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
-- 
1.9.1



[PATCH v6 2/6] arm: dts: mt2701: Add usb2 device nodes

2019-06-04 Thread min.guo
From: Min Guo 

Add musb nodes and usb2 phy nodes for MT2701

Signed-off-by: Min Guo 
---
changes in v6:
1. Modify usb connector child node

changes in v5:
1. Add usb connector child node

changes in v4:
1. no changes

changes in v3:
1. no changes

changes in v2:
1. Remove phy-names
---
 arch/arm/boot/dts/mt2701-evb.dts | 21 +
 arch/arm/boot/dts/mt2701.dtsi| 33 +
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index 88f8fd2..bf53e2b 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -6,6 +6,7 @@
  */
 
 /dts-v1/;
+#include 
 #include "mt2701.dtsi"
 
 / {
@@ -61,6 +62,15 @@
>;
default-brightness-level = <9>;
};
+
+   usb_vbus: regulator@0 {
+   compatible = "regulator-fixed";
+   regulator-name = "usb_vbus";
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <500>;
+   gpio = <&pio 45 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
 };
 
 &auxadc {
@@ -230,3 +240,14 @@
 &uart0 {
status = "okay";
 };
+
+&usb2 {
+   status = "okay";
+   connector{
+   compatible = "linux,typeb-conn-gpio", "usb-b-connector";
+   label = "micro-USB";
+   type = "micro";
+   id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
+   vbus-supply = <&usb_vbus>;
+   };
+};
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 51e1305..80a3b55 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -671,6 +671,39 @@
};
};
 
+   usb2: usb@1120 {
+   compatible = "mediatek,mt2701-musb",
+"mediatek,mtk-musb";
+   reg = <0 0x1120 0 0x1000>;
+   interrupts = ;
+   interrupt-names = "mc";
+   phys = <&u2port2 PHY_TYPE_USB2>;
+   dr_mode = "otg";
+   clocks = <&pericfg CLK_PERI_USB0>,
+<&pericfg CLK_PERI_USB0_MCU>,
+<&pericfg CLK_PERI_USB_SLV>;
+   clock-names = "main","mcu","univpll";
+   power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+   status = "disabled";
+   };
+
+   u2phy0: usb-phy@1121 {
+   compatible = "mediatek,generic-tphy-v1";
+   reg = <0 0x1121 0 0x0800>;
+   #address-cells = <2>;
+   #size-cells = <2>;
+   ranges;
+   status = "okay";
+
+   u2port2: usb-phy@1a1c4800 {
+   reg = <0 0x11210800 0 0x0100>;
+   clocks = <&topckgen CLK_TOP_USB_PHY48M>;
+   clock-names = "ref";
+   #phy-cells = <1>;
+   status = "okay";
+   };
+   };
+
ethsys: syscon@1b00 {
compatible = "mediatek,mt2701-ethsys", "syscon";
reg = <0 0x1b00 0 0x1000>;
-- 
1.9.1



[PATCH v6 4/6] usb: musb: Add noirq type of dma create interface

2019-06-04 Thread min.guo
From: Min Guo 

Add noirq type of dma create interface for platform which do not
have dedicated DMA interrupt line, move musbhsdma macro definition
to musb_dma.h

Signed-off-by: Min Guo 
---
changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_dma.h  |  9 
 drivers/usb/musb/musbhsdma.c | 54 ++--
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 8f60271..05103ea 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -35,6 +35,12 @@
  *whether shared with the Inventra core or separate.
  */
 
+#define MUSB_HSDMA_BASE0x200
+#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL 0x4
+#define MUSB_HSDMA_ADDRESS 0x8
+#define MUSB_HSDMA_COUNT   0xc
+
 #defineDMA_ADDR_INVALID(~(dma_addr_t)0)
 
 #ifdef CONFIG_MUSB_PIO_ONLY
@@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct 
dma_controller *d) { }
 extern struct dma_controller *
 musbhs_dma_controller_create(struct musb *musb, void __iomem *base);
 extern void musbhs_dma_controller_destroy(struct dma_controller *c);
+extern struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base);
+extern irqreturn_t dma_controller_irq(int irq, void *private_data);
 
 extern struct dma_controller *
 tusb_dma_controller_create(struct musb *musb, void __iomem *base);
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 5fc6825..d549c0b 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -10,12 +10,7 @@
 #include 
 #include 
 #include "musb_core.h"
-
-#define MUSB_HSDMA_BASE0x200
-#define MUSB_HSDMA_INTR(MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL 0x4
-#define MUSB_HSDMA_ADDRESS 0x8
-#define MUSB_HSDMA_COUNT   0xc
+#include "musb_dma.h"
 
 #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)  \
(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
@@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel)
return 0;
 }
 
-static irqreturn_t dma_controller_irq(int irq, void *private_data)
+irqreturn_t dma_controller_irq(int irq, void *private_data)
 {
struct musb_dma_controller *controller = private_data;
struct musb *musb = controller->private_data;
@@ -383,6 +378,7 @@ static irqreturn_t dma_controller_irq(int irq, void 
*private_data)
spin_unlock_irqrestore(&musb->lock, flags);
return retval;
 }
+EXPORT_SYMBOL_GPL(dma_controller_irq);
 
 void musbhs_dma_controller_destroy(struct dma_controller *c)
 {
@@ -398,18 +394,10 @@ void musbhs_dma_controller_destroy(struct dma_controller 
*c)
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy);
 
-struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
-   void __iomem *base)
+static struct musb_dma_controller *
+dma_controller_alloc(struct musb *musb, void __iomem *base)
 {
struct musb_dma_controller *controller;
-   struct device *dev = musb->controller;
-   struct platform_device *pdev = to_platform_device(dev);
-   int irq = platform_get_irq_byname(pdev, "dma");
-
-   if (irq <= 0) {
-   dev_err(dev, "No DMA interrupt line!\n");
-   return NULL;
-   }
 
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
@@ -423,6 +411,25 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
controller->controller.channel_release = dma_channel_release;
controller->controller.channel_program = dma_channel_program;
controller->controller.channel_abort = dma_channel_abort;
+   return controller;
+}
+
+struct dma_controller *
+musbhs_dma_controller_create(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *controller;
+   struct device *dev = musb->controller;
+   struct platform_device *pdev = to_platform_device(dev);
+   int irq = platform_get_irq_byname(pdev, "dma");
+
+   if (irq <= 0) {
+   dev_err(dev, "No DMA interrupt line!\n");
+   return NULL;
+   }
+
+   controller = dma_controller_alloc(musb, base);
+   if (!controller)
+   return NULL;
 
if (request_irq(irq, dma_controller_irq, 0,
dev_name(musb->controller), &controller->controller)) {
@@ -437,3 +444,16 @@ struct dma_controller *musbhs_dma_controller_create(struct 
musb *musb,
return &controller->controller;
 }
 EXPORT_SYMBOL_GPL(musbhs_dma_controller_create);
+
+struct dma_controller *
+musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base)
+{
+   struct musb_dma_controller *cont

[PATCH v6 6/6] usb: musb: Add support for MediaTek musb controller

2019-06-04 Thread min.guo
From: Min Guo 

This adds support for MediaTek musb controller in
host, peripheral and otg mode.
There are some quirk of MediaTek musb controller, such as:
 -W1C interrupt status registers
 -Private data toggle registers
 -No dedicated DMA interrupt line

Signed-off-by: Min Guo 
Signed-off-by: Yonglong Wu 
---
changes in v6:
1. Add of_platform_populate in probe to populate connector platform_devices
   from device tree data
2. Replace extcon with usb role switch mechanism to support dual-role mode
3. Remove set vbus function

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending 
interrupts
2. Make musb_clearb/w() return the value of musb_readb/w()
3. Add driver to get child nodes of usb connector and extcon device

changes in v4:
1. no changes

changes in v3:
suggested by Bin:
1. Remove 'u8/u16 data' parameter in clearb/w() hooks
2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status

changes in v2:
suggested by Bin:
1. Add summarize of MediaTek musb controller differences in the commit log
2. Add "|| COMPILE_TEST" in Kconfig
3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c
4. Replace musb_readl() with musb_readw() to read 16bit toggle register
---
 drivers/usb/musb/Kconfig|   9 +-
 drivers/usb/musb/Makefile   |   1 +
 drivers/usb/musb/mediatek.c | 582 
 3 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/musb/mediatek.c

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 52f8e2b..767c5da 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -116,6 +116,13 @@ config USB_MUSB_JZ4740
depends on USB_MUSB_GADGET
depends on USB=n || USB_OTG_BLACKLIST_HUB
 
+config USB_MUSB_MEDIATEK
+   tristate "MediaTek platforms"
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   depends on NOP_USB_XCEIV
+   depends on GENERIC_PHY
+   select USB_ROLE_SWITCH
+
 config USB_MUSB_AM335X_CHILD
tristate
 
@@ -142,7 +149,7 @@ config USB_UX500_DMA
 
 config USB_INVENTRA_DMA
bool 'Inventra'
-   depends on USB_MUSB_OMAP2PLUS
+   depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK
help
  Enable DMA transfers using Mentor's engine.
 
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 3a88c79..63d82d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)  += da8xx.o
 obj-$(CONFIG_USB_MUSB_UX500)   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)  += jz4740.o
 obj-$(CONFIG_USB_MUSB_SUNXI)   += sunxi.o
+obj-$(CONFIG_USB_MUSB_MEDIATEK)+= mediatek.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)+= musb_am335x.o
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
new file mode 100644
index 000..3df8d7e
--- /dev/null
+++ b/drivers/usb/musb/mediatek.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author:
+ *  Min Guo 
+ *  Yonglong Wu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "musb_core.h"
+#include "musb_dma.h"
+
+#define USB_L1INTS 0x00a0
+#define USB_L1INTM 0x00a4
+#define MTK_MUSB_TXFUNCADDR0x0480
+
+/* MediaTek controller toggle enable and status reg */
+#define MUSB_RXTOG 0x80
+#define MUSB_RXTOGEN   0x82
+#define MUSB_TXTOG 0x84
+#define MUSB_TXTOGEN   0x86
+#define MTK_TOGGLE_EN  GENMASK(15, 0)
+
+#define TX_INT_STATUS  BIT(0)
+#define RX_INT_STATUS  BIT(1)
+#define USBCOM_INT_STATUS  BIT(2)
+#define DMA_INT_STATUS BIT(3)
+
+#define DMA_INTR_STATUS_MSKGENMASK(7, 0)
+#define DMA_INTR_UNMASK_SET_MSKGENMASK(31, 24)
+
+struct mtk_glue {
+   struct device *dev;
+   struct musb *musb;
+   struct platform_device *musb_pdev;
+   struct platform_device *usb_phy;
+   struct phy *phy;
+   struct usb_phy *xceiv;
+   enum phy_mode phy_mode;
+   struct clk *main;
+   struct clk *mcu;
+   struct clk *univpll;
+   enum usb_role role;
+   struct usb_role_switch *role_sw;
+};
+
+static int mtk_musb_clks_get(struct mtk_glue *glue)
+{
+   struct device *dev = glue->dev;
+
+   glue->main = devm_clk_get(dev, "main");
+   if (IS_ERR(glue->main)) {
+   dev_err(dev, "fail to get main clock\n");
+   return PTR_ERR(glue->main);
+   }
+
+   glue->mcu = devm_clk_get(dev, "mcu");
+   if (IS_ERR(glue->mcu)) {
+   dev_err(dev, "fail to get mcu clock\n");
+   return PTR_ERR(glue->mcu);
+   }
+
+   glue->univpll = devm_clk_get(dev, "univpll");
+   if (IS_ERR(glue->univpll)) {
+   dev_err(dev, "fail to get univpll clock\n");
+   return PTR_ERR(glue

[PATCH v6 3/6] usb: musb: Add get/set toggle hooks

2019-06-04 Thread min.guo
From: Min Guo 

Add get/set toggle hooks in struct musb_io and struct musb_platform_ops
for special platform; remove function musb_save_toggle, use the set/get
callback to handle toggle.

Signed-off-by: Min Guo 
---
changes in v6:
1. no changes

changes in v5:
1. no changes

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 42 
 drivers/usb/musb/musb_core.h |  5 +
 drivers/usb/musb/musb_host.c | 46 ++--
 drivers/usb/musb/musb_io.h   |  4 
 4 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 9f5a481..491d361 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -274,6 +274,38 @@ static void musb_default_writew(void __iomem *addr, 
unsigned offset, u16 data)
__raw_writew(data, addr + offset);
 }
 
+static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out)
+{
+   void __iomem *epio = qh->hw_ep->regs;
+   u16 csr;
+
+   if (is_out)
+   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+   else
+   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+
+   return csr;
+}
+
+static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out,
+  struct urb *urb)
+{
+   u16 csr;
+   u16 toggle;
+
+   toggle = usb_gettoggle(urb->dev, qh->epnum, is_out);
+
+   if (is_out)
+   csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
+   | MUSB_TXCSR_H_DATATOGGLE)
+   : MUSB_TXCSR_CLRDATATOG;
+   else
+   csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
+   | MUSB_RXCSR_H_DATATOGGLE) : 0;
+
+   return csr;
+}
+
 /*
  * Load an endpoint's FIFO
  */
@@ -2278,6 +2310,16 @@ static void musb_deassert_reset(struct work_struct *work)
else
musb->io.write_fifo = musb_default_write_fifo;
 
+   if (musb->ops->get_toggle)
+   musb->io.get_toggle = musb->ops->get_toggle;
+   else
+   musb->io.get_toggle = musb_default_get_toggle;
+
+   if (musb->ops->set_toggle)
+   musb->io.set_toggle = musb->ops->set_toggle;
+   else
+   musb->io.set_toggle = musb_default_set_toggle;
+
if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7..9f5a69c 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -27,6 +27,7 @@
 struct musb;
 struct musb_hw_ep;
 struct musb_ep;
+struct musb_qh;
 
 /* Helper defines for struct musb->hwvers */
 #define MUSB_HWVERS_MAJOR(x)   ((x >> 10) & 0x1f)
@@ -123,6 +124,8 @@ enum musb_g_ep0_state {
  * @writew:write 16 bits
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
+ * @get_toggle:platform specific get toggle function
+ * @set_toggle:platform specific set toggle function
  * @dma_init:  platform specific dma init function
  * @dma_exit:  platform specific dma exit function
  * @init:  turns on clocks, sets up platform-specific registers, etc
@@ -167,6 +170,8 @@ struct musb_platform_ops {
void(*writew)(void __iomem *addr, unsigned offset, u16 data);
void(*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void(*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
+   u16 (*get_toggle)(struct musb_qh *qh, int is_out);
+   u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
struct dma_controller *
(*dma_init) (struct musb *musb, void __iomem *base);
void(*dma_exit)(struct dma_controller *c);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index eb308ec..ca866bc 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -286,26 +286,6 @@ static void musb_giveback(struct musb *musb, struct urb 
*urb, int status)
spin_lock(&musb->lock);
 }
 
-/* For bulk/interrupt endpoints only */
-static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
-   struct urb *urb)
-{
-   void __iomem*epio = qh->hw_ep->regs;
-   u16 csr;
-
-   /*
-* FIXME: the current Mentor DMA code seems to have
-* problems getting toggle correct.
-*/
-
-   if (is_in)
-   csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
-   else
-   csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
-
-   usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
-}
-
 /*
  * Advance this hardware endpoint's queue, completing the specified URB and
  * advancing to either the next URB queued t

[PATCH v5 5/6] usb: musb: Add musb_clearb/w() interface

2019-06-04 Thread min.guo
From: Min Guo 

Delete the const attribute of addr parameter in readb/w/l hooks, these
changes are for implementing clearing W1C registers.
Replace musb_readb/w with musb_clearb/w to clear the interrupt status.

Signed-off-by: Min Guo 
---
changes in v6:
1. no changes

changes in v5:
1. Replace musb_readb() with musb_clearb() to clear dma pending interrupts

new patch based on v4:
---
 drivers/usb/musb/musb_core.c | 32 +++-
 drivers/usb/musb/musb_core.h |  8 ++--
 drivers/usb/musb/musb_io.h   |  8 +---
 drivers/usb/musb/musbhsdma.c |  2 +-
 drivers/usb/musb/sunxi.c |  4 ++--
 drivers/usb/musb/tusb6010.c  |  2 +-
 6 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 491d361..8528726 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -246,7 +246,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset)
return 0x80 + (0x08 * epnum) + offset;
 }
 
-static u8 musb_default_readb(const void __iomem *addr, unsigned offset)
+static u8 musb_default_readb(void __iomem *addr, unsigned offset)
 {
u8 data =  __raw_readb(addr + offset);
 
@@ -260,7 +260,7 @@ static void musb_default_writeb(void __iomem *addr, 
unsigned offset, u8 data)
__raw_writeb(data, addr + offset);
 }
 
-static u16 musb_default_readw(const void __iomem *addr, unsigned offset)
+static u16 musb_default_readw(void __iomem *addr, unsigned offset)
 {
u16 data = __raw_readw(addr + offset);
 
@@ -396,19 +396,25 @@ static void musb_default_read_fifo(struct musb_hw_ep 
*hw_ep, u16 len, u8 *dst)
 /*
  * Old style IO functions
  */
-u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+u8 (*musb_readb)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readb);
 
 void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
 EXPORT_SYMBOL_GPL(musb_writeb);
 
-u16 (*musb_readw)(const void __iomem *addr, unsigned offset);
+u8 (*musb_clearb)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearb);
+
+u16 (*musb_readw)(void __iomem *addr, unsigned offset);
 EXPORT_SYMBOL_GPL(musb_readw);
 
 void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data);
 EXPORT_SYMBOL_GPL(musb_writew);
 
-u32 musb_readl(const void __iomem *addr, unsigned offset)
+u16 (*musb_clearw)(void __iomem *addr, unsigned int offset);
+EXPORT_SYMBOL_GPL(musb_clearw);
+
+u32 musb_readl(void __iomem *addr, unsigned offset)
 {
u32 data = __raw_readl(addr + offset);
 
@@ -1047,7 +1053,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 
int_usb,
 static void musb_disable_interrupts(struct musb *musb)
 {
void __iomem*mbase = musb->mregs;
-   u16 temp;
 
/* disable interrupts */
musb_writeb(mbase, MUSB_INTRUSBE, 0);
@@ -1057,9 +1062,9 @@ static void musb_disable_interrupts(struct musb *musb)
musb_writew(mbase, MUSB_INTRRXE, 0);
 
/*  flush pending interrupts */
-   temp = musb_readb(mbase, MUSB_INTRUSB);
-   temp = musb_readw(mbase, MUSB_INTRTX);
-   temp = musb_readw(mbase, MUSB_INTRRX);
+   musb_clearb(mbase, MUSB_INTRUSB);
+   musb_clearw(mbase, MUSB_INTRTX);
+   musb_clearw(mbase, MUSB_INTRRX);
 }
 
 static void musb_enable_interrupts(struct musb *musb)
@@ -2285,10 +2290,19 @@ static void musb_deassert_reset(struct work_struct 
*work)
musb_readb = musb->ops->readb;
if (musb->ops->writeb)
musb_writeb = musb->ops->writeb;
+   if (musb->ops->clearb)
+   musb_clearb = musb->ops->clearb;
+   else
+   musb_clearb = musb_readb;
+
if (musb->ops->readw)
musb_readw = musb->ops->readw;
if (musb->ops->writew)
musb_writew = musb->ops->writew;
+   if (musb->ops->clearw)
+   musb_clearw = musb->ops->clearw;
+   else
+   musb_clearw = musb_readw;
 
 #ifndef CONFIG_MUSB_PIO_ONLY
if (!musb->ops->dma_init || !musb->ops->dma_exit) {
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 9f5a69c..0d9a35f 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -120,8 +120,10 @@ enum musb_g_ep0_state {
  * @fifo_offset: returns the fifo offset
  * @readb: read 8 bits
  * @writeb:write 8 bits
+ * @clearb:could be clear-on-readb or W1C
  * @readw: read 16 bits
  * @writew:write 16 bits
+ * @clearw:could be clear-on-readw or W1C
  * @read_fifo: reads the fifo
  * @write_fifo:writes to fifo
  * @get_toggle:platform specific get toggle function
@@ -164,10 +166,12 @@ struct musb_platform_ops {
u16 fifo_mode;
u32 (*fifo_offset)(u8 epnum);
u32 (*busctl_offset)(u8 epnum, u16 offset);
-   u8  (*readb)(const void __iomem *addr, unsigned offset);
+   u8  (*readb)(void __iomem *addr, unsigned offset);
void