Browse Source

Merge tag 'usb-for-v4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: changes for v4.15 merge window

Not much going on this time around. With only 51 non-merge commits,
this was one of the smallest pull requests from the Gadget tree.

Most of the changes are in the mtu3 driver which added support for
36-bit DMA, support for USB 3.1 and support for dual-role (along with
some non-critical fixes).

The dwc2 driver got a few improvements to how we handle gadget state
tracking and also added support for STM32F7xx devices.

Other than that, we just some minor non-critical fixes and
improvements all over the place.
Greg Kroah-Hartman 7 years ago
parent
commit
2d5afd51fe
42 changed files with 862 additions and 367 deletions
  1. 2 0
      Documentation/devicetree/bindings/usb/dwc2.txt
  2. 10 9
      Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
  3. 4 0
      Documentation/devicetree/bindings/usb/renesas_usb3.txt
  4. 4 1
      Documentation/devicetree/bindings/usb/renesas_usbhs.txt
  5. 4 0
      drivers/usb/dwc2/core.h
  6. 7 0
      drivers/usb/dwc2/gadget.c
  7. 10 2
      drivers/usb/dwc2/hcd.c
  8. 14 0
      drivers/usb/dwc2/params.c
  9. 28 33
      drivers/usb/dwc3/core.c
  10. 2 0
      drivers/usb/dwc3/core.h
  11. 26 3
      drivers/usb/dwc3/dwc3-of-simple.c
  12. 27 2
      drivers/usb/dwc3/dwc3-pci.c
  13. 0 20
      drivers/usb/dwc3/ep0.c
  14. 20 42
      drivers/usb/dwc3/gadget.c
  15. 1 0
      drivers/usb/gadget/function/f_tcm.c
  16. 1 0
      drivers/usb/gadget/function/u_serial.c
  17. 1 1
      drivers/usb/gadget/function/uvc_v4l2.c
  18. 1 1
      drivers/usb/gadget/function/uvc_v4l2.h
  19. 1 1
      drivers/usb/gadget/udc/core.c
  20. 39 26
      drivers/usb/gadget/udc/dummy_hcd.c
  21. 9 5
      drivers/usb/gadget/udc/goku_udc.c
  22. 1 1
      drivers/usb/gadget/udc/gr_udc.c
  23. 61 10
      drivers/usb/gadget/udc/renesas_usb3.c
  24. 37 11
      drivers/usb/mtu3/mtu3.h
  25. 53 8
      drivers/usb/mtu3/mtu3_core.c
  26. 45 16
      drivers/usb/mtu3/mtu3_dr.c
  27. 6 0
      drivers/usb/mtu3/mtu3_dr.h
  28. 2 1
      drivers/usb/mtu3/mtu3_gadget.c
  29. 8 8
      drivers/usb/mtu3/mtu3_gadget_ep0.c
  30. 22 56
      drivers/usb/mtu3/mtu3_host.c
  31. 13 0
      drivers/usb/mtu3/mtu3_hw_regs.h
  32. 88 77
      drivers/usb/mtu3/mtu3_plat.c
  33. 84 18
      drivers/usb/mtu3/mtu3_qmu.c
  34. 4 1
      drivers/usb/phy/phy-generic.c
  35. 1 0
      drivers/usb/phy/phy-msm-usb.c
  36. 154 0
      drivers/usb/phy/phy-mxs-usb.c
  37. 2 1
      drivers/usb/phy/phy-tahvo.c
  38. 13 11
      drivers/usb/renesas_usbhs/common.c
  39. 48 0
      drivers/usb/renesas_usbhs/rcar3.c
  40. 1 0
      drivers/usb/renesas_usbhs/rcar3.h
  41. 5 0
      include/linux/usb/gadget.h
  42. 3 2
      include/linux/usb/renesas_usbhs.h

+ 2 - 0
Documentation/devicetree/bindings/usb/dwc2.txt

@@ -19,6 +19,8 @@ Required properties:
   configured in FS mode;
   configured in FS mode;
   - "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in STM32F4x9 SoCs
   - "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in STM32F4x9 SoCs
   configured in HS mode;
   configured in HS mode;
+  - "st,stm32f7xx-hsotg": The DWC2 USB HS controller instance in STM32F7xx SoCs
+    configured in HS mode;
 - reg : Should contain 1 register range (address and length)
 - reg : Should contain 1 register range (address and length)
 - interrupts : Should contain 1 interrupt
 - interrupts : Should contain 1 interrupt
 - clocks: clock provider specifier
 - clocks: clock provider specifier

+ 10 - 9
Documentation/devicetree/bindings/usb/mediatek,mtu3.txt

@@ -14,9 +14,9 @@ Required properties:
  - vusb33-supply : regulator of USB avdd3.3v
  - vusb33-supply : regulator of USB avdd3.3v
  - clocks : a list of phandle + clock-specifier pairs, one for each
  - clocks : a list of phandle + clock-specifier pairs, one for each
 	entry in clock-names
 	entry in clock-names
- - clock-names : must contain "sys_ck" and "ref_ck" for clock of controller;
-	"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
-	depends on "mediatek,enable-wakeup"
+ - clock-names : must contain "sys_ck" for clock of controller,
+	the following clocks are optional:
+	"ref_ck", "mcu_ck" and "dam_ck";
  - phys : a list of phandle + phy specifier pairs
  - phys : a list of phandle + phy specifier pairs
  - dr_mode : should be one of "host", "peripheral" or "otg",
  - dr_mode : should be one of "host", "peripheral" or "otg",
 	refer to usb/generic.txt
 	refer to usb/generic.txt
@@ -30,9 +30,10 @@ Optional properties:
 	when supports dual-role mode.
 	when supports dual-role mode.
  - vbus-supply : reference to the VBUS regulator, needed when supports
  - vbus-supply : reference to the VBUS regulator, needed when supports
 	dual-role mode.
 	dual-role mode.
- - pinctl-names : a pinctrl state named "default" must be defined,
-	"id_float" and "id_ground" are optinal which depends on
-	"mediatek,enable-manual-drd"
+ - pinctrl-names : a pinctrl state named "default" is optional, and need be
+	defined if auto drd switch is enabled, that means the property dr_mode
+	is set as "otg", and meanwhile the property "mediatek,enable-manual-drd"
+	is not set.
  - pinctrl-0 : pin control group
  - pinctrl-0 : pin control group
 	See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 	See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
 
@@ -44,6 +45,8 @@ Optional properties:
  - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
  - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
  - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
  - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
 	control register, it depends on "mediatek,enable-wakeup".
 	control register, it depends on "mediatek,enable-wakeup".
+ - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
+	bit1 for u3port1, ... etc;
 
 
 Sub-nodes:
 Sub-nodes:
 The xhci should be added as subnode to mtu3 as shown in the following example
 The xhci should be added as subnode to mtu3 as shown in the following example
@@ -63,9 +66,7 @@ ssusb: usb@11271000 {
 	clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
 	clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
 		 <&pericfg CLK_PERI_USB0>,
 		 <&pericfg CLK_PERI_USB0>,
 		 <&pericfg CLK_PERI_USB1>;
 		 <&pericfg CLK_PERI_USB1>;
-	clock-names = "sys_ck", "ref_ck",
-		      "wakeup_deb_p0",
-		      "wakeup_deb_p1";
+	clock-names = "sys_ck", "ref_ck";
 	vusb33-supply = <&mt6397_vusb_reg>;
 	vusb33-supply = <&mt6397_vusb_reg>;
 	vbus-supply = <&usb_p0_vbus>;
 	vbus-supply = <&usb_p0_vbus>;
 	extcon = <&extcon_usb>;
 	extcon = <&extcon_usb>;

+ 4 - 0
Documentation/devicetree/bindings/usb/renesas_usb3.txt

@@ -15,6 +15,10 @@ Required properties:
   - interrupts: Interrupt specifier for the USB3.0 Peripheral
   - interrupts: Interrupt specifier for the USB3.0 Peripheral
   - clocks: clock phandle and specifier pair
   - clocks: clock phandle and specifier pair
 
 
+Optional properties:
+  - phys: phandle + phy specifier pair
+  - phy-names: must be "usb"
+
 Example of R-Car H3 ES1.x:
 Example of R-Car H3 ES1.x:
 	usb3_peri0: usb@ee020000 {
 	usb3_peri0: usb@ee020000 {
 		compatible = "renesas,r8a7795-usb3-peri",
 		compatible = "renesas,r8a7795-usb3-peri",

+ 4 - 1
Documentation/devicetree/bindings/usb/renesas_usbhs.txt

@@ -3,6 +3,8 @@ Renesas Electronics USBHS driver
 Required properties:
 Required properties:
   - compatible: Must contain one or more of the following:
   - compatible: Must contain one or more of the following:
 
 
+	- "renesas,usbhs-r8a7743" for r8a7743 (RZ/G1M) compatible device
+	- "renesas,usbhs-r8a7745" for r8a7745 (RZ/G1E) compatible device
 	- "renesas,usbhs-r8a7790" for r8a7790 (R-Car H2) compatible device
 	- "renesas,usbhs-r8a7790" for r8a7790 (R-Car H2) compatible device
 	- "renesas,usbhs-r8a7791" for r8a7791 (R-Car M2-W) compatible device
 	- "renesas,usbhs-r8a7791" for r8a7791 (R-Car M2-W) compatible device
 	- "renesas,usbhs-r8a7792" for r8a7792 (R-Car V2H) compatible device
 	- "renesas,usbhs-r8a7792" for r8a7792 (R-Car V2H) compatible device
@@ -10,7 +12,8 @@ Required properties:
 	- "renesas,usbhs-r8a7794" for r8a7794 (R-Car E2) compatible device
 	- "renesas,usbhs-r8a7794" for r8a7794 (R-Car E2) compatible device
 	- "renesas,usbhs-r8a7795" for r8a7795 (R-Car H3) compatible device
 	- "renesas,usbhs-r8a7795" for r8a7795 (R-Car H3) compatible device
 	- "renesas,usbhs-r8a7796" for r8a7796 (R-Car M3-W) compatible device
 	- "renesas,usbhs-r8a7796" for r8a7796 (R-Car M3-W) compatible device
-	- "renesas,rcar-gen2-usbhs" for R-Car Gen2 compatible device
+	- "renesas,usbhs-r8a77995" for r8a77995 (R-Car D3) compatible device
+	- "renesas,rcar-gen2-usbhs" for R-Car Gen2 or RZ/G1 compatible devices
 	- "renesas,rcar-gen3-usbhs" for R-Car Gen3 compatible device
 	- "renesas,rcar-gen3-usbhs" for R-Car Gen3 compatible device
 
 
 	When compatible with the generic version, nodes must list the
 	When compatible with the generic version, nodes must list the

+ 4 - 0
drivers/usb/dwc2/core.h

@@ -395,6 +395,9 @@ enum dwc2_ep0_state {
  *                           (default when phy_type is UTMI+ or ULPI)
  *                           (default when phy_type is UTMI+ or ULPI)
  *                       1 - 6 MHz
  *                       1 - 6 MHz
  *                           (default when phy_type is Full Speed)
  *                           (default when phy_type is Full Speed)
+ * @oc_disable:		Flag to disable overcurrent condition.
+ *			0 - Allow overcurrent condition to get detected
+ *			1 - Disable overcurrent condtion to get detected
  * @ts_dline:           Enable Term Select Dline pulsing
  * @ts_dline:           Enable Term Select Dline pulsing
  *                       0 - No (default)
  *                       0 - No (default)
  *                       1 - Yes
  *                       1 - Yes
@@ -492,6 +495,7 @@ struct dwc2_core_params {
 	bool dma_desc_fs_enable;
 	bool dma_desc_fs_enable;
 	bool host_support_fs_ls_low_power;
 	bool host_support_fs_ls_low_power;
 	bool host_ls_low_power_phy_clk;
 	bool host_ls_low_power_phy_clk;
+	bool oc_disable;
 
 
 	u8 host_channels;
 	u8 host_channels;
 	u16 host_rx_fifo_size;
 	u16 host_rx_fifo_size;

+ 7 - 0
drivers/usb/dwc2/gadget.c

@@ -3202,6 +3202,8 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
 
 
 	call_gadget(hsotg, disconnect);
 	call_gadget(hsotg, disconnect);
 	hsotg->lx_state = DWC2_L3;
 	hsotg->lx_state = DWC2_L3;
+
+	usb_gadget_set_state(&hsotg->gadget, USB_STATE_NOTATTACHED);
 }
 }
 
 
 /**
 /**
@@ -4004,6 +4006,11 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
+	if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
+		dev_err(hsotg->dev, "%s: called in host mode?\n", __func__);
+		return -EINVAL;
+	}
+
 	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 
 
 	spin_lock_irqsave(&hsotg->lock, flags);
 	spin_lock_irqsave(&hsotg->lock, flags);

+ 10 - 2
drivers/usb/dwc2/hcd.c

@@ -213,6 +213,11 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 		usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
 		usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
 		if (hsotg->params.phy_ulpi_ddr)
 		if (hsotg->params.phy_ulpi_ddr)
 			usbcfg |= GUSBCFG_DDRSEL;
 			usbcfg |= GUSBCFG_DDRSEL;
+
+		/* Set external VBUS indicator as needed. */
+		if (hsotg->params.oc_disable)
+			usbcfg |= (GUSBCFG_ULPI_INT_VBUS_IND |
+				   GUSBCFG_INDICATORPASSTHROUGH);
 		break;
 		break;
 	case DWC2_PHY_TYPE_PARAM_UTMI:
 	case DWC2_PHY_TYPE_PARAM_UTMI:
 		/* UTMI+ interface */
 		/* UTMI+ interface */
@@ -3277,7 +3282,6 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 		dwc2_core_init(hsotg, false);
 		dwc2_core_init(hsotg, false);
 		dwc2_enable_global_interrupts(hsotg);
 		dwc2_enable_global_interrupts(hsotg);
 		spin_lock_irqsave(&hsotg->lock, flags);
 		spin_lock_irqsave(&hsotg->lock, flags);
-		dwc2_hsotg_disconnect(hsotg);
 		dwc2_hsotg_core_init_disconnected(hsotg, false);
 		dwc2_hsotg_core_init_disconnected(hsotg, false);
 		spin_unlock_irqrestore(&hsotg->lock, flags);
 		spin_unlock_irqrestore(&hsotg->lock, flags);
 		dwc2_hsotg_core_connect(hsotg);
 		dwc2_hsotg_core_connect(hsotg);
@@ -3296,8 +3300,12 @@ host:
 		if (count > 250)
 		if (count > 250)
 			dev_err(hsotg->dev,
 			dev_err(hsotg->dev,
 				"Connection id status change timed out\n");
 				"Connection id status change timed out\n");
-		hsotg->op_state = OTG_STATE_A_HOST;
 
 
+		spin_lock_irqsave(&hsotg->lock, flags);
+		dwc2_hsotg_disconnect(hsotg);
+		spin_unlock_irqrestore(&hsotg->lock, flags);
+
+		hsotg->op_state = OTG_STATE_A_HOST;
 		/* Initialize the Core for Host mode */
 		/* Initialize the Core for Host mode */
 		dwc2_core_init(hsotg, false);
 		dwc2_core_init(hsotg, false);
 		dwc2_enable_global_interrupts(hsotg);
 		dwc2_enable_global_interrupts(hsotg);

+ 14 - 0
drivers/usb/dwc2/params.c

@@ -136,6 +136,15 @@ static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg)
 	p->activate_stm_fs_transceiver = true;
 	p->activate_stm_fs_transceiver = true;
 }
 }
 
 
+static void dwc2_set_stm32f7xx_hsotg_params(struct dwc2_hsotg *hsotg)
+{
+	struct dwc2_core_params *p = &hsotg->params;
+
+	p->host_rx_fifo_size = 622;
+	p->host_nperio_tx_fifo_size = 128;
+	p->host_perio_tx_fifo_size = 256;
+}
+
 const struct of_device_id dwc2_of_match_table[] = {
 const struct of_device_id dwc2_of_match_table[] = {
 	{ .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params },
 	{ .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params },
 	{ .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params  },
 	{ .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params  },
@@ -154,6 +163,8 @@ const struct of_device_id dwc2_of_match_table[] = {
 	{ .compatible = "st,stm32f4x9-fsotg",
 	{ .compatible = "st,stm32f4x9-fsotg",
 	  .data = dwc2_set_stm32f4x9_fsotg_params },
 	  .data = dwc2_set_stm32f4x9_fsotg_params },
 	{ .compatible = "st,stm32f4x9-hsotg" },
 	{ .compatible = "st,stm32f4x9-hsotg" },
+	{ .compatible = "st,stm32f7xx-hsotg",
+	  .data = dwc2_set_stm32f7xx_hsotg_params },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
 MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
@@ -335,6 +346,9 @@ static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg)
 						       num);
 						       num);
 		}
 		}
 	}
 	}
+
+	if (of_find_property(hsotg->dev->of_node, "disable-over-current", NULL))
+		p->oc_disable = true;
 }
 }
 
 
 static void dwc2_check_param_otg_cap(struct dwc2_hsotg *hsotg)
 static void dwc2_check_param_otg_cap(struct dwc2_hsotg *hsotg)

+ 28 - 33
drivers/usb/dwc3/core.c

@@ -156,9 +156,8 @@ static void __dwc3_set_mode(struct work_struct *work)
 		} else {
 		} else {
 			if (dwc->usb2_phy)
 			if (dwc->usb2_phy)
 				otg_set_vbus(dwc->usb2_phy->otg, true);
 				otg_set_vbus(dwc->usb2_phy->otg, true);
-			if (dwc->usb2_generic_phy)
-				phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
-
+			phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
+			phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
 		}
 		}
 		break;
 		break;
 	case DWC3_GCTL_PRTCAP_DEVICE:
 	case DWC3_GCTL_PRTCAP_DEVICE:
@@ -166,8 +165,8 @@ static void __dwc3_set_mode(struct work_struct *work)
 
 
 		if (dwc->usb2_phy)
 		if (dwc->usb2_phy)
 			otg_set_vbus(dwc->usb2_phy->otg, false);
 			otg_set_vbus(dwc->usb2_phy->otg, false);
-		if (dwc->usb2_generic_phy)
-			phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
+		phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
+		phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);
 
 
 		ret = dwc3_gadget_init(dwc);
 		ret = dwc3_gadget_init(dwc);
 		if (ret)
 		if (ret)
@@ -927,12 +926,13 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
 
 
 	switch (dwc->dr_mode) {
 	switch (dwc->dr_mode) {
 	case USB_DR_MODE_PERIPHERAL:
 	case USB_DR_MODE_PERIPHERAL:
+		dwc->current_dr_role = DWC3_GCTL_PRTCAP_DEVICE;
 		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 
 
 		if (dwc->usb2_phy)
 		if (dwc->usb2_phy)
 			otg_set_vbus(dwc->usb2_phy->otg, false);
 			otg_set_vbus(dwc->usb2_phy->otg, false);
-		if (dwc->usb2_generic_phy)
-			phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
+		phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
+		phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);
 
 
 		ret = dwc3_gadget_init(dwc);
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
 		if (ret) {
@@ -942,12 +942,13 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
 		}
 		}
 		break;
 		break;
 	case USB_DR_MODE_HOST:
 	case USB_DR_MODE_HOST:
+		dwc->current_dr_role = DWC3_GCTL_PRTCAP_HOST;
 		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
 		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
 
 
 		if (dwc->usb2_phy)
 		if (dwc->usb2_phy)
 			otg_set_vbus(dwc->usb2_phy->otg, true);
 			otg_set_vbus(dwc->usb2_phy->otg, true);
-		if (dwc->usb2_generic_phy)
-			phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
+		phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
+		phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
 
 
 		ret = dwc3_host_init(dwc);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
 		if (ret) {
@@ -1293,21 +1294,19 @@ static int dwc3_suspend_common(struct dwc3 *dwc)
 {
 {
 	unsigned long	flags;
 	unsigned long	flags;
 
 
-	switch (dwc->dr_mode) {
-	case USB_DR_MODE_PERIPHERAL:
-	case USB_DR_MODE_OTG:
+	switch (dwc->current_dr_role) {
+	case DWC3_GCTL_PRTCAP_DEVICE:
 		spin_lock_irqsave(&dwc->lock, flags);
 		spin_lock_irqsave(&dwc->lock, flags);
 		dwc3_gadget_suspend(dwc);
 		dwc3_gadget_suspend(dwc);
 		spin_unlock_irqrestore(&dwc->lock, flags);
 		spin_unlock_irqrestore(&dwc->lock, flags);
+		dwc3_core_exit(dwc);
 		break;
 		break;
-	case USB_DR_MODE_HOST:
+	case DWC3_GCTL_PRTCAP_HOST:
 	default:
 	default:
 		/* do nothing */
 		/* do nothing */
 		break;
 		break;
 	}
 	}
 
 
-	dwc3_core_exit(dwc);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1316,18 +1315,17 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 	unsigned long	flags;
 	unsigned long	flags;
 	int		ret;
 	int		ret;
 
 
-	ret = dwc3_core_init(dwc);
-	if (ret)
-		return ret;
+	switch (dwc->current_dr_role) {
+	case DWC3_GCTL_PRTCAP_DEVICE:
+		ret = dwc3_core_init(dwc);
+		if (ret)
+			return ret;
 
 
-	switch (dwc->dr_mode) {
-	case USB_DR_MODE_PERIPHERAL:
-	case USB_DR_MODE_OTG:
 		spin_lock_irqsave(&dwc->lock, flags);
 		spin_lock_irqsave(&dwc->lock, flags);
 		dwc3_gadget_resume(dwc);
 		dwc3_gadget_resume(dwc);
 		spin_unlock_irqrestore(&dwc->lock, flags);
 		spin_unlock_irqrestore(&dwc->lock, flags);
-		/* FALLTHROUGH */
-	case USB_DR_MODE_HOST:
+		break;
+	case DWC3_GCTL_PRTCAP_HOST:
 	default:
 	default:
 		/* do nothing */
 		/* do nothing */
 		break;
 		break;
@@ -1338,7 +1336,7 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 
 
 static int dwc3_runtime_checks(struct dwc3 *dwc)
 static int dwc3_runtime_checks(struct dwc3 *dwc)
 {
 {
-	switch (dwc->dr_mode) {
+	switch (dwc->current_dr_role) {
 	case USB_DR_MODE_PERIPHERAL:
 	case USB_DR_MODE_PERIPHERAL:
 	case USB_DR_MODE_OTG:
 	case USB_DR_MODE_OTG:
 		if (dwc->connected)
 		if (dwc->connected)
@@ -1381,19 +1379,17 @@ static int dwc3_runtime_resume(struct device *dev)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	switch (dwc->dr_mode) {
-	case USB_DR_MODE_PERIPHERAL:
-	case USB_DR_MODE_OTG:
+	switch (dwc->current_dr_role) {
+	case DWC3_GCTL_PRTCAP_DEVICE:
 		dwc3_gadget_process_pending_events(dwc);
 		dwc3_gadget_process_pending_events(dwc);
 		break;
 		break;
-	case USB_DR_MODE_HOST:
+	case DWC3_GCTL_PRTCAP_HOST:
 	default:
 	default:
 		/* do nothing */
 		/* do nothing */
 		break;
 		break;
 	}
 	}
 
 
 	pm_runtime_mark_last_busy(dev);
 	pm_runtime_mark_last_busy(dev);
-	pm_runtime_put(dev);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1402,13 +1398,12 @@ static int dwc3_runtime_idle(struct device *dev)
 {
 {
 	struct dwc3     *dwc = dev_get_drvdata(dev);
 	struct dwc3     *dwc = dev_get_drvdata(dev);
 
 
-	switch (dwc->dr_mode) {
-	case USB_DR_MODE_PERIPHERAL:
-	case USB_DR_MODE_OTG:
+	switch (dwc->current_dr_role) {
+	case DWC3_GCTL_PRTCAP_DEVICE:
 		if (dwc3_runtime_checks(dwc))
 		if (dwc3_runtime_checks(dwc))
 			return -EBUSY;
 			return -EBUSY;
 		break;
 		break;
-	case USB_DR_MODE_HOST:
+	case DWC3_GCTL_PRTCAP_HOST:
 	default:
 	default:
 		/* do nothing */
 		/* do nothing */
 		break;
 		break;

+ 2 - 0
drivers/usb/dwc3/core.h

@@ -529,6 +529,7 @@ struct dwc3_event_buffer {
  * @number: endpoint number (1 - 15)
  * @number: endpoint number (1 - 15)
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
  * @resource_index: Resource transfer index
  * @resource_index: Resource transfer index
+ * @frame_number: set to the frame number we want this transfer to start (ISOC)
  * @interval: the interval on which the ISOC transfer is started
  * @interval: the interval on which the ISOC transfer is started
  * @allocated_requests: number of requests allocated
  * @allocated_requests: number of requests allocated
  * @queued_requests: number of requests queued for transfer
  * @queued_requests: number of requests queued for transfer
@@ -581,6 +582,7 @@ struct dwc3_ep {
 	u8			resource_index;
 	u8			resource_index;
 	u32			allocated_requests;
 	u32			allocated_requests;
 	u32			queued_requests;
 	u32			queued_requests;
+	u32			frame_number;
 	u32			interval;
 	u32			interval;
 
 
 	char			name[20];
 	char			name[20];

+ 26 - 3
drivers/usb/dwc3/dwc3-of-simple.c

@@ -28,11 +28,13 @@
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
+#include <linux/reset.h>
 
 
 struct dwc3_of_simple {
 struct dwc3_of_simple {
 	struct device		*dev;
 	struct device		*dev;
 	struct clk		**clks;
 	struct clk		**clks;
 	int			num_clocks;
 	int			num_clocks;
+	struct reset_control	*resets;
 };
 };
 
 
 static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
 static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
@@ -95,10 +97,21 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, simple);
 	platform_set_drvdata(pdev, simple);
 	simple->dev = dev;
 	simple->dev = dev;
 
 
+	simple->resets = of_reset_control_array_get_optional_exclusive(np);
+	if (IS_ERR(simple->resets)) {
+		ret = PTR_ERR(simple->resets);
+		dev_err(dev, "failed to get device resets, err=%d\n", ret);
+		return ret;
+	}
+
+	ret = reset_control_deassert(simple->resets);
+	if (ret)
+		goto err_resetc_put;
+
 	ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np,
 	ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np,
 						"clocks", "#clock-cells"));
 						"clocks", "#clock-cells"));
 	if (ret)
 	if (ret)
-		return ret;
+		goto err_resetc_assert;
 
 
 	ret = of_platform_populate(np, NULL, NULL, dev);
 	ret = of_platform_populate(np, NULL, NULL, dev);
 	if (ret) {
 	if (ret) {
@@ -107,7 +120,7 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
 			clk_put(simple->clks[i]);
 			clk_put(simple->clks[i]);
 		}
 		}
 
 
-		return ret;
+		goto err_resetc_assert;
 	}
 	}
 
 
 	pm_runtime_set_active(dev);
 	pm_runtime_set_active(dev);
@@ -115,6 +128,13 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
 	pm_runtime_get_sync(dev);
 	pm_runtime_get_sync(dev);
 
 
 	return 0;
 	return 0;
+
+err_resetc_assert:
+	reset_control_assert(simple->resets);
+
+err_resetc_put:
+	reset_control_put(simple->resets);
+	return ret;
 }
 }
 
 
 static int dwc3_of_simple_remove(struct platform_device *pdev)
 static int dwc3_of_simple_remove(struct platform_device *pdev)
@@ -123,12 +143,15 @@ static int dwc3_of_simple_remove(struct platform_device *pdev)
 	struct device		*dev = &pdev->dev;
 	struct device		*dev = &pdev->dev;
 	int			i;
 	int			i;
 
 
+	of_platform_depopulate(dev);
+
 	for (i = 0; i < simple->num_clocks; i++) {
 	for (i = 0; i < simple->num_clocks; i++) {
 		clk_disable_unprepare(simple->clks[i]);
 		clk_disable_unprepare(simple->clks[i]);
 		clk_put(simple->clks[i]);
 		clk_put(simple->clks[i]);
 	}
 	}
 
 
-	of_platform_depopulate(dev);
+	reset_control_assert(simple->resets);
+	reset_control_put(simple->resets);
 
 
 	pm_runtime_put_sync(dev);
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 	pm_runtime_disable(dev);

+ 27 - 2
drivers/usb/dwc3/dwc3-pci.c

@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/consumer.h>
@@ -61,6 +62,7 @@ struct dwc3_pci {
 	guid_t guid;
 	guid_t guid;
 
 
 	unsigned int has_dsm_for_pm:1;
 	unsigned int has_dsm_for_pm:1;
+	struct work_struct wakeup_work;
 };
 };
 
 
 static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
 static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
@@ -174,6 +176,22 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
 	return 0;
 	return 0;
 }
 }
 
 
+#ifdef CONFIG_PM
+static void dwc3_pci_resume_work(struct work_struct *work)
+{
+	struct dwc3_pci *dwc = container_of(work, struct dwc3_pci, wakeup_work);
+	struct platform_device *dwc3 = dwc->dwc3;
+	int ret;
+
+	ret = pm_runtime_get_sync(&dwc3->dev);
+	if (ret)
+		return;
+
+	pm_runtime_mark_last_busy(&dwc3->dev);
+	pm_runtime_put_sync_autosuspend(&dwc3->dev);
+}
+#endif
+
 static int dwc3_pci_probe(struct pci_dev *pci,
 static int dwc3_pci_probe(struct pci_dev *pci,
 		const struct pci_device_id *id)
 		const struct pci_device_id *id)
 {
 {
@@ -232,6 +250,9 @@ static int dwc3_pci_probe(struct pci_dev *pci,
 	device_init_wakeup(dev, true);
 	device_init_wakeup(dev, true);
 	pci_set_drvdata(pci, dwc);
 	pci_set_drvdata(pci, dwc);
 	pm_runtime_put(dev);
 	pm_runtime_put(dev);
+#ifdef CONFIG_PM
+	INIT_WORK(&dwc->wakeup_work, dwc3_pci_resume_work);
+#endif
 
 
 	return 0;
 	return 0;
 err:
 err:
@@ -243,6 +264,9 @@ static void dwc3_pci_remove(struct pci_dev *pci)
 {
 {
 	struct dwc3_pci		*dwc = pci_get_drvdata(pci);
 	struct dwc3_pci		*dwc = pci_get_drvdata(pci);
 
 
+#ifdef CONFIG_PM
+	cancel_work_sync(&dwc->wakeup_work);
+#endif
 	device_init_wakeup(&pci->dev, false);
 	device_init_wakeup(&pci->dev, false);
 	pm_runtime_get(&pci->dev);
 	pm_runtime_get(&pci->dev);
 	platform_device_unregister(dwc->dwc3);
 	platform_device_unregister(dwc->dwc3);
@@ -318,14 +342,15 @@ static int dwc3_pci_runtime_suspend(struct device *dev)
 static int dwc3_pci_runtime_resume(struct device *dev)
 static int dwc3_pci_runtime_resume(struct device *dev)
 {
 {
 	struct dwc3_pci		*dwc = dev_get_drvdata(dev);
 	struct dwc3_pci		*dwc = dev_get_drvdata(dev);
-	struct platform_device	*dwc3 = dwc->dwc3;
 	int			ret;
 	int			ret;
 
 
 	ret = dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
 	ret = dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	return pm_runtime_get(&dwc3->dev);
+	queue_work(pm_wq, &dwc->wakeup_work);
+
+	return 0;
 }
 }
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PM */
 
 

+ 0 - 20
drivers/usb/dwc3/ep0.c

@@ -487,14 +487,10 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
 static int dwc3_ep0_handle_intf(struct dwc3 *dwc,
 static int dwc3_ep0_handle_intf(struct dwc3 *dwc,
 		struct usb_ctrlrequest *ctrl, int set)
 		struct usb_ctrlrequest *ctrl, int set)
 {
 {
-	enum usb_device_state	state;
 	u32			wValue;
 	u32			wValue;
-	u32			wIndex;
 	int			ret = 0;
 	int			ret = 0;
 
 
 	wValue = le16_to_cpu(ctrl->wValue);
 	wValue = le16_to_cpu(ctrl->wValue);
-	wIndex = le16_to_cpu(ctrl->wIndex);
-	state = dwc->gadget.state;
 
 
 	switch (wValue) {
 	switch (wValue) {
 	case USB_INTRF_FUNC_SUSPEND:
 	case USB_INTRF_FUNC_SUSPEND:
@@ -517,14 +513,10 @@ static int dwc3_ep0_handle_endpoint(struct dwc3 *dwc,
 		struct usb_ctrlrequest *ctrl, int set)
 		struct usb_ctrlrequest *ctrl, int set)
 {
 {
 	struct dwc3_ep		*dep;
 	struct dwc3_ep		*dep;
-	enum usb_device_state	state;
 	u32			wValue;
 	u32			wValue;
-	u32			wIndex;
 	int			ret;
 	int			ret;
 
 
 	wValue = le16_to_cpu(ctrl->wValue);
 	wValue = le16_to_cpu(ctrl->wValue);
-	wIndex = le16_to_cpu(ctrl->wIndex);
-	state = dwc->gadget.state;
 
 
 	switch (wValue) {
 	switch (wValue) {
 	case USB_ENDPOINT_HALT:
 	case USB_ENDPOINT_HALT:
@@ -551,10 +543,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 {
 {
 	u32			recip;
 	u32			recip;
 	int			ret;
 	int			ret;
-	enum usb_device_state	state;
 
 
 	recip = ctrl->bRequestType & USB_RECIP_MASK;
 	recip = ctrl->bRequestType & USB_RECIP_MASK;
-	state = dwc->gadget.state;
 
 
 	switch (recip) {
 	switch (recip) {
 	case USB_RECIP_DEVICE:
 	case USB_RECIP_DEVICE:
@@ -712,12 +702,10 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 	struct dwc3_ep	*dep;
 	struct dwc3_ep	*dep;
 	enum usb_device_state state = dwc->gadget.state;
 	enum usb_device_state state = dwc->gadget.state;
 	u16		wLength;
 	u16		wLength;
-	u16		wValue;
 
 
 	if (state == USB_STATE_DEFAULT)
 	if (state == USB_STATE_DEFAULT)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	wValue = le16_to_cpu(ctrl->wValue);
 	wLength = le16_to_cpu(ctrl->wLength);
 	wLength = le16_to_cpu(ctrl->wLength);
 
 
 	if (wLength != 6) {
 	if (wLength != 6) {
@@ -842,9 +830,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 	struct usb_request	*ur;
 	struct usb_request	*ur;
 	struct dwc3_trb		*trb;
 	struct dwc3_trb		*trb;
 	struct dwc3_ep		*ep0;
 	struct dwc3_ep		*ep0;
-	unsigned		maxp;
-	unsigned		remaining_ur_length;
-	void			*buf;
 	u32			transferred = 0;
 	u32			transferred = 0;
 	u32			status;
 	u32			status;
 	u32			length;
 	u32			length;
@@ -871,11 +856,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 	}
 	}
 
 
 	ur = &r->request;
 	ur = &r->request;
-	buf = ur->buf;
-	remaining_ur_length = ur->length;
 
 
 	length = trb->size & DWC3_TRB_SIZE_MASK;
 	length = trb->size & DWC3_TRB_SIZE_MASK;
-	maxp = ep0->endpoint.maxpacket;
 	transferred = ur->length - length;
 	transferred = ur->length - length;
 	ur->actual += transferred;
 	ur->actual += transferred;
 
 
@@ -1001,7 +983,6 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
 	} else if (IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) &&
 	} else if (IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) &&
 		   req->request.length && req->request.zero) {
 		   req->request.length && req->request.zero) {
 		u32	maxpacket;
 		u32	maxpacket;
-		u32	rem;
 
 
 		ret = usb_gadget_map_request_by_dev(dwc->sysdev,
 		ret = usb_gadget_map_request_by_dev(dwc->sysdev,
 				&req->request, dep->number);
 				&req->request, dep->number);
@@ -1009,7 +990,6 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
 			return;
 			return;
 
 
 		maxpacket = dep->endpoint.maxpacket;
 		maxpacket = dep->endpoint.maxpacket;
-		rem = req->request.length % maxpacket;
 
 
 		/* prepare normal TRB */
 		/* prepare normal TRB */
 		dwc3_ep0_prepare_one_trb(dep, req->request.dma,
 		dwc3_ep0_prepare_one_trb(dep, req->request.dma,

+ 20 - 42
drivers/usb/dwc3/gadget.c

@@ -1151,9 +1151,6 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 
 
 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
 
 
-	if (!dwc3_calc_trbs_left(dep))
-		return;
-
 	/*
 	/*
 	 * We can get in a situation where there's a request in the started list
 	 * We can get in a situation where there's a request in the started list
 	 * but there weren't enough TRBs to fully kick it in the first time
 	 * but there weren't enough TRBs to fully kick it in the first time
@@ -1194,7 +1191,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 	}
 	}
 }
 }
 
 
-static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)
+static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
 {
 {
 	struct dwc3_gadget_ep_cmd_params params;
 	struct dwc3_gadget_ep_cmd_params params;
 	struct dwc3_request		*req;
 	struct dwc3_request		*req;
@@ -1202,6 +1199,9 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)
 	int				ret;
 	int				ret;
 	u32				cmd;
 	u32				cmd;
 
 
+	if (!dwc3_calc_trbs_left(dep))
+		return 0;
+
 	starting = !(dep->flags & DWC3_EP_BUSY);
 	starting = !(dep->flags & DWC3_EP_BUSY);
 
 
 	dwc3_prepare_trbs(dep);
 	dwc3_prepare_trbs(dep);
@@ -1216,8 +1216,10 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)
 	if (starting) {
 	if (starting) {
 		params.param0 = upper_32_bits(req->trb_dma);
 		params.param0 = upper_32_bits(req->trb_dma);
 		params.param1 = lower_32_bits(req->trb_dma);
 		params.param1 = lower_32_bits(req->trb_dma);
-		cmd = DWC3_DEPCMD_STARTTRANSFER |
-			DWC3_DEPCMD_PARAM(cmd_param);
+		cmd = DWC3_DEPCMD_STARTTRANSFER;
+
+		if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
+			cmd |= DWC3_DEPCMD_PARAM(dep->frame_number);
 	} else {
 	} else {
 		cmd = DWC3_DEPCMD_UPDATETRANSFER |
 		cmd = DWC3_DEPCMD_UPDATETRANSFER |
 			DWC3_DEPCMD_PARAM(dep->resource_index);
 			DWC3_DEPCMD_PARAM(dep->resource_index);
@@ -1258,8 +1260,6 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
 static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
 static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
 		struct dwc3_ep *dep, u32 cur_uf)
 		struct dwc3_ep *dep, u32 cur_uf)
 {
 {
-	u32 uf;
-
 	if (list_empty(&dep->pending_list)) {
 	if (list_empty(&dep->pending_list)) {
 		dev_info(dwc->dev, "%s: ran out of requests\n",
 		dev_info(dwc->dev, "%s: ran out of requests\n",
 				dep->name);
 				dep->name);
@@ -1271,9 +1271,8 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
 	 * Schedule the first trb for one interval in the future or at
 	 * Schedule the first trb for one interval in the future or at
 	 * least 4 microframes.
 	 * least 4 microframes.
 	 */
 	 */
-	uf = cur_uf + max_t(u32, 4, dep->interval);
-
-	__dwc3_gadget_kick_transfer(dep, uf);
+	dep->frame_number = cur_uf + max_t(u32, 4, dep->interval);
+	__dwc3_gadget_kick_transfer(dep);
 }
 }
 
 
 static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
 static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
@@ -1290,7 +1289,6 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
 static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 {
 {
 	struct dwc3		*dwc = dep->dwc;
 	struct dwc3		*dwc = dep->dwc;
-	int			ret = 0;
 
 
 	if (!dep->endpoint.desc) {
 	if (!dep->endpoint.desc) {
 		dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
 		dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
@@ -1337,24 +1335,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		}
 		}
 
 
 		if ((dep->flags & DWC3_EP_BUSY) &&
 		if ((dep->flags & DWC3_EP_BUSY) &&
-		    !(dep->flags & DWC3_EP_MISSED_ISOC)) {
-			WARN_ON_ONCE(!dep->resource_index);
-			ret = __dwc3_gadget_kick_transfer(dep,
-							  dep->resource_index);
-		}
-
-		goto out;
-	}
+		    !(dep->flags & DWC3_EP_MISSED_ISOC))
+			goto out;
 
 
-	if (!dwc3_calc_trbs_left(dep))
 		return 0;
 		return 0;
+	}
 
 
-	ret = __dwc3_gadget_kick_transfer(dep, 0);
 out:
 out:
-	if (ret == -EBUSY)
-		ret = 0;
-
-	return ret;
+	return __dwc3_gadget_kick_transfer(dep);
 }
 }
 
 
 static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
 static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
@@ -2347,7 +2335,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 		req->request.actual = length - req->remaining;
 		req->request.actual = length - req->remaining;
 
 
 		if ((req->request.actual < length) && req->num_pending_sgs)
 		if ((req->request.actual < length) && req->num_pending_sgs)
-			return __dwc3_gadget_kick_transfer(dep, 0);
+			return __dwc3_gadget_kick_transfer(dep);
 
 
 		dwc3_gadget_giveback(dep, req, status);
 		dwc3_gadget_giveback(dep, req, status);
 
 
@@ -2440,13 +2428,8 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
 	if (!dep->endpoint.desc)
 	if (!dep->endpoint.desc)
 		return;
 		return;
 
 
-	if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-		int ret;
-
-		ret = __dwc3_gadget_kick_transfer(dep, 0);
-		if (!ret || ret == -EBUSY)
-			return;
-	}
+	if (!usb_endpoint_xfer_isoc(dep->endpoint.desc))
+		__dwc3_gadget_kick_transfer(dep);
 }
 }
 
 
 static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
@@ -2487,15 +2470,10 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		break;
 		break;
 	case DWC3_DEPEVT_XFERNOTREADY:
 	case DWC3_DEPEVT_XFERNOTREADY:
-		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+		if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
 			dwc3_gadget_start_isoc(dwc, dep, event);
 			dwc3_gadget_start_isoc(dwc, dep, event);
-		} else {
-			int ret;
-
-			ret = __dwc3_gadget_kick_transfer(dep, 0);
-			if (!ret || ret == -EBUSY)
-				return;
-		}
+		else
+			__dwc3_gadget_kick_transfer(dep);
 
 
 		break;
 		break;
 	case DWC3_DEPEVT_STREAMEVT:
 	case DWC3_DEPEVT_STREAMEVT:

+ 1 - 0
drivers/usb/gadget/function/f_tcm.c

@@ -1145,6 +1145,7 @@ static int usbg_submit_command(struct f_uas *fu,
 	default:
 	default:
 		pr_debug_once("Unsupported prio_attr: %02x.\n",
 		pr_debug_once("Unsupported prio_attr: %02x.\n",
 				cmd_iu->prio_attr);
 				cmd_iu->prio_attr);
+		/* fall through */
 	case UAS_SIMPLE_TAG:
 	case UAS_SIMPLE_TAG:
 		cmd->prio_attr = TCM_SIMPLE_TAG;
 		cmd->prio_attr = TCM_SIMPLE_TAG;
 		break;
 		break;

+ 1 - 0
drivers/usb/gadget/function/u_serial.c

@@ -1078,6 +1078,7 @@ static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
 	default:
 	default:
 		pr_warn("%s: unexpected %s status %d\n",
 		pr_warn("%s: unexpected %s status %d\n",
 			__func__, ep->name, req->status);
 			__func__, ep->name, req->status);
+		/* fall through */
 	case 0:
 	case 0:
 		/* normal completion */
 		/* normal completion */
 		spin_lock(&info->con_lock);
 		spin_lock(&info->con_lock);

+ 1 - 1
drivers/usb/gadget/function/uvc_v4l2.c

@@ -354,7 +354,7 @@ static unsigned long uvcg_v4l2_get_unmapped_area(struct file *file,
 }
 }
 #endif
 #endif
 
 
-struct v4l2_file_operations uvc_v4l2_fops = {
+const struct v4l2_file_operations uvc_v4l2_fops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.open		= uvc_v4l2_open,
 	.open		= uvc_v4l2_open,
 	.release	= uvc_v4l2_release,
 	.release	= uvc_v4l2_release,

+ 1 - 1
drivers/usb/gadget/function/uvc_v4l2.h

@@ -17,6 +17,6 @@
 #define __UVC_V4L2_H__
 #define __UVC_V4L2_H__
 
 
 extern const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops;
 extern const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops;
-extern struct v4l2_file_operations uvc_v4l2_fops;
+extern const struct v4l2_file_operations uvc_v4l2_fops;
 
 
 #endif /* __UVC_V4L2_H__ */
 #endif /* __UVC_V4L2_H__ */

+ 1 - 1
drivers/usb/gadget/udc/core.c

@@ -912,7 +912,7 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
 		return 0;
 		return 0;
 
 
 	type = usb_endpoint_type(desc);
 	type = usb_endpoint_type(desc);
-	max = 0x7ff & usb_endpoint_maxp(desc);
+	max = usb_endpoint_maxp(desc);
 
 
 	if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
 	if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
 		return 0;
 		return 0;

+ 39 - 26
drivers/usb/gadget/udc/dummy_hcd.c

@@ -23,6 +23,8 @@
  *
  *
  * Having this all in one kernel can help some stages of development,
  * Having this all in one kernel can help some stages of development,
  * bypassing some hardware (and driver) issues.  UML could help too.
  * bypassing some hardware (and driver) issues.  UML could help too.
+ *
+ * Note: The emulation does not include isochronous transfers!
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -137,6 +139,9 @@ static const struct {
 		.caps = _caps, \
 		.caps = _caps, \
 	}
 	}
 
 
+/* we don't provide isochronous endpoints since we don't support them */
+#define TYPE_BULK_OR_INT	(USB_EP_CAPS_TYPE_BULK | USB_EP_CAPS_TYPE_INT)
+
 	/* everyone has ep0 */
 	/* everyone has ep0 */
 	EP_INFO(ep0name,
 	EP_INFO(ep0name,
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
@@ -145,64 +150,72 @@ static const struct {
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep2out-bulk",
 	EP_INFO("ep2out-bulk",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+/*
 	EP_INFO("ep3in-iso",
 	EP_INFO("ep3in-iso",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep4out-iso",
 	EP_INFO("ep4out-iso",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+*/
 	EP_INFO("ep5in-int",
 	EP_INFO("ep5in-int",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep6in-bulk",
 	EP_INFO("ep6in-bulk",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep7out-bulk",
 	EP_INFO("ep7out-bulk",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+/*
 	EP_INFO("ep8in-iso",
 	EP_INFO("ep8in-iso",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep9out-iso",
 	EP_INFO("ep9out-iso",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+*/
 	EP_INFO("ep10in-int",
 	EP_INFO("ep10in-int",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep11in-bulk",
 	EP_INFO("ep11in-bulk",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep12out-bulk",
 	EP_INFO("ep12out-bulk",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+/*
 	EP_INFO("ep13in-iso",
 	EP_INFO("ep13in-iso",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep14out-iso",
 	EP_INFO("ep14out-iso",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+*/
 	EP_INFO("ep15in-int",
 	EP_INFO("ep15in-int",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+
 	/* or like sa1100: two fixed function endpoints */
 	/* or like sa1100: two fixed function endpoints */
 	EP_INFO("ep1out-bulk",
 	EP_INFO("ep1out-bulk",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep2in-bulk",
 	EP_INFO("ep2in-bulk",
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
 		USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+
 	/* and now some generic EPs so we have enough in multi config */
 	/* and now some generic EPs so we have enough in multi config */
 	EP_INFO("ep3out",
 	EP_INFO("ep3out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep4in",
 	EP_INFO("ep4in",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep5out",
 	EP_INFO("ep5out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep6out",
 	EP_INFO("ep6out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep7in",
 	EP_INFO("ep7in",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep8out",
 	EP_INFO("ep8out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep9in",
 	EP_INFO("ep9in",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep10out",
 	EP_INFO("ep10out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep11out",
 	EP_INFO("ep11out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep12in",
 	EP_INFO("ep12in",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep13out",
 	EP_INFO("ep13out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 	EP_INFO("ep14in",
 	EP_INFO("ep14in",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
 	EP_INFO("ep15out",
 	EP_INFO("ep15out",
-		USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+		USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
 
 
 #undef EP_INFO
 #undef EP_INFO
 };
 };
@@ -1769,6 +1782,7 @@ static void dummy_timer(unsigned long _dum_hcd)
 	int			i;
 	int			i;
 
 
 	/* simplistic model for one frame's bandwidth */
 	/* simplistic model for one frame's bandwidth */
+	/* FIXME: account for transaction and packet overhead */
 	switch (dum->gadget.speed) {
 	switch (dum->gadget.speed) {
 	case USB_SPEED_LOW:
 	case USB_SPEED_LOW:
 		total = 8/*bytes*/ * 12/*packets*/;
 		total = 8/*bytes*/ * 12/*packets*/;
@@ -1813,7 +1827,6 @@ restart:
 		struct dummy_request	*req;
 		struct dummy_request	*req;
 		u8			address;
 		u8			address;
 		struct dummy_ep		*ep = NULL;
 		struct dummy_ep		*ep = NULL;
-		int			type;
 		int			status = -EINPROGRESS;
 		int			status = -EINPROGRESS;
 
 
 		/* stop when we reach URBs queued after the timer interrupt */
 		/* stop when we reach URBs queued after the timer interrupt */
@@ -1825,14 +1838,10 @@ restart:
 			goto return_urb;
 			goto return_urb;
 		else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
 		else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
 			continue;
 			continue;
-		type = usb_pipetype(urb->pipe);
 
 
-		/* used up this frame's non-periodic bandwidth?
-		 * FIXME there's infinite bandwidth for control and
-		 * periodic transfers ... unrealistic.
-		 */
-		if (total <= 0 && type == PIPE_BULK)
-			continue;
+		/* Used up this frame's bandwidth? */
+		if (total <= 0)
+			break;
 
 
 		/* find the gadget's ep for this request (if configured) */
 		/* find the gadget's ep for this request (if configured) */
 		address = usb_pipeendpoint (urb->pipe);
 		address = usb_pipeendpoint (urb->pipe);
@@ -1930,13 +1939,17 @@ restart:
 		limit = total;
 		limit = total;
 		switch (usb_pipetype(urb->pipe)) {
 		switch (usb_pipetype(urb->pipe)) {
 		case PIPE_ISOCHRONOUS:
 		case PIPE_ISOCHRONOUS:
-			/* FIXME is it urb->interval since the last xfer?
-			 * use urb->iso_frame_desc[i].
-			 * complete whether or not ep has requests queued.
-			 * report random errors, to debug drivers.
+			/*
+			 * We don't support isochronous.  But if we did,
+			 * here are some of the issues we'd have to face:
+			 *
+			 * Is it urb->interval since the last xfer?
+			 * Use urb->iso_frame_desc[i].
+			 * Complete whether or not ep has requests queued.
+			 * Report random errors, to debug drivers.
 			 */
 			 */
 			limit = max(limit, periodic_bytes(dum, ep));
 			limit = max(limit, periodic_bytes(dum, ep));
-			status = -ENOSYS;
+			status = -EINVAL;	/* fail all xfers */
 			break;
 			break;
 
 
 		case PIPE_INTERRUPT:
 		case PIPE_INTERRUPT:

+ 9 - 5
drivers/usb/gadget/udc/goku_udc.c

@@ -127,11 +127,15 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	mode = 0;
 	mode = 0;
 	max = get_unaligned_le16(&desc->wMaxPacketSize);
 	max = get_unaligned_le16(&desc->wMaxPacketSize);
 	switch (max) {
 	switch (max) {
-	case 64:	mode++;
-	case 32:	mode++;
-	case 16:	mode++;
-	case 8:		mode <<= 3;
-			break;
+	case 64:
+		mode++; /* fall through */
+	case 32:
+		mode++; /* fall through */
+	case 16:
+		mode++; /* fall through */
+	case 8:
+		mode <<= 3;
+		break;
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}

+ 1 - 1
drivers/usb/gadget/udc/gr_udc.c

@@ -1538,7 +1538,7 @@ static int gr_ep_enable(struct usb_ep *_ep,
 	 * Bits 10-0 set the max payload. 12-11 set the number of
 	 * Bits 10-0 set the max payload. 12-11 set the number of
 	 * additional transactions.
 	 * additional transactions.
 	 */
 	 */
-	max = 0x7ff & usb_endpoint_maxp(desc);
+	max = usb_endpoint_maxp(desc);
 	nt = usb_endpoint_maxp_mult(desc) - 1;
 	nt = usb_endpoint_maxp_mult(desc) - 1;
 	buffer_size = GR_BUFFER_SIZE(epctrl);
 	buffer_size = GR_BUFFER_SIZE(epctrl);
 	if (nt && (mode == 0 || mode == 2)) {
 	if (nt && (mode == 0 || mode == 2)) {

+ 61 - 10
drivers/usb/gadget/udc/renesas_usb3.c

@@ -1,7 +1,7 @@
 /*
 /*
  * Renesas USB3.0 Peripheral driver (USB gadget)
  * Renesas USB3.0 Peripheral driver (USB gadget)
  *
  *
- * Copyright (C) 2015  Renesas Electronics Corporation
+ * Copyright (C) 2015-2017  Renesas Electronics Corporation
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/sizes.h>
 #include <linux/sizes.h>
@@ -334,6 +335,7 @@ struct renesas_usb3 {
 	struct usb_gadget_driver *driver;
 	struct usb_gadget_driver *driver;
 	struct extcon_dev *extcon;
 	struct extcon_dev *extcon;
 	struct work_struct extcon_work;
 	struct work_struct extcon_work;
+	struct phy *phy;
 
 
 	struct renesas_usb3_ep *usb3_ep;
 	struct renesas_usb3_ep *usb3_ep;
 	int num_usb3_eps;
 	int num_usb3_eps;
@@ -2239,7 +2241,9 @@ static int renesas_usb3_start(struct usb_gadget *gadget,
 	/* hook up the driver */
 	/* hook up the driver */
 	usb3->driver = driver;
 	usb3->driver = driver;
 
 
-	pm_runtime_enable(usb3_to_dev(usb3));
+	if (usb3->phy)
+		phy_init(usb3->phy);
+
 	pm_runtime_get_sync(usb3_to_dev(usb3));
 	pm_runtime_get_sync(usb3_to_dev(usb3));
 
 
 	renesas_usb3_init_controller(usb3);
 	renesas_usb3_init_controller(usb3);
@@ -2256,8 +2260,10 @@ static int renesas_usb3_stop(struct usb_gadget *gadget)
 	usb3->driver = NULL;
 	usb3->driver = NULL;
 	renesas_usb3_stop_controller(usb3);
 	renesas_usb3_stop_controller(usb3);
 
 
+	if (usb3->phy)
+		phy_exit(usb3->phy);
+
 	pm_runtime_put(usb3_to_dev(usb3));
 	pm_runtime_put(usb3_to_dev(usb3));
-	pm_runtime_disable(usb3_to_dev(usb3));
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2405,6 +2411,9 @@ static int renesas_usb3_remove(struct platform_device *pdev)
 	renesas_usb3_dma_free_prd(usb3, &pdev->dev);
 	renesas_usb3_dma_free_prd(usb3, &pdev->dev);
 
 
 	__renesas_usb3_ep_free_request(usb3->ep0_req);
 	__renesas_usb3_ep_free_request(usb3->ep0_req);
+	if (usb3->phy)
+		phy_put(usb3->phy);
+	pm_runtime_disable(usb3_to_dev(usb3));
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2560,20 +2569,15 @@ static int renesas_usb3_probe(struct platform_device *pdev)
 {
 {
 	struct renesas_usb3 *usb3;
 	struct renesas_usb3 *usb3;
 	struct resource *res;
 	struct resource *res;
-	const struct of_device_id *match;
 	int irq, ret;
 	int irq, ret;
 	const struct renesas_usb3_priv *priv;
 	const struct renesas_usb3_priv *priv;
 	const struct soc_device_attribute *attr;
 	const struct soc_device_attribute *attr;
 
 
-	match = of_match_node(usb3_of_match, pdev->dev.of_node);
-	if (!match)
-		return -ENODEV;
-
 	attr = soc_device_match(renesas_usb3_quirks_match);
 	attr = soc_device_match(renesas_usb3_quirks_match);
 	if (attr)
 	if (attr)
 		priv = attr->data;
 		priv = attr->data;
 	else
 	else
-		priv = match->data;
+		priv = of_device_get_match_data(&pdev->dev);
 
 
 	irq = platform_get_irq(pdev, 0);
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 	if (irq < 0) {
@@ -2635,11 +2639,20 @@ static int renesas_usb3_probe(struct platform_device *pdev)
 	if (ret < 0)
 	if (ret < 0)
 		goto err_dev_create;
 		goto err_dev_create;
 
 
+	/*
+	 * This is an optional. So, if this driver cannot get a phy,
+	 * this driver will not handle a phy anymore.
+	 */
+	usb3->phy = devm_phy_get(&pdev->dev, "usb");
+	if (IS_ERR(usb3->phy))
+		usb3->phy = NULL;
+
 	usb3->workaround_for_vbus = priv->workaround_for_vbus;
 	usb3->workaround_for_vbus = priv->workaround_for_vbus;
 
 
 	renesas_usb3_debugfs_init(usb3, &pdev->dev);
 	renesas_usb3_debugfs_init(usb3, &pdev->dev);
 
 
-	dev_info(&pdev->dev, "probed\n");
+	dev_info(&pdev->dev, "probed%s\n", usb3->phy ? " with phy" : "");
+	pm_runtime_enable(usb3_to_dev(usb3));
 
 
 	return 0;
 	return 0;
 
 
@@ -2655,11 +2668,49 @@ err_alloc_prd:
 	return ret;
 	return ret;
 }
 }
 
 
+#ifdef CONFIG_PM_SLEEP
+static int renesas_usb3_suspend(struct device *dev)
+{
+	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
+
+	/* Not started */
+	if (!usb3->driver)
+		return 0;
+
+	renesas_usb3_stop_controller(usb3);
+	if (usb3->phy)
+		phy_exit(usb3->phy);
+	pm_runtime_put(dev);
+
+	return 0;
+}
+
+static int renesas_usb3_resume(struct device *dev)
+{
+	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
+
+	/* Not started */
+	if (!usb3->driver)
+		return 0;
+
+	if (usb3->phy)
+		phy_init(usb3->phy);
+	pm_runtime_get_sync(dev);
+	renesas_usb3_init_controller(usb3);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(renesas_usb3_pm_ops, renesas_usb3_suspend,
+			renesas_usb3_resume);
+
 static struct platform_driver renesas_usb3_driver = {
 static struct platform_driver renesas_usb3_driver = {
 	.probe		= renesas_usb3_probe,
 	.probe		= renesas_usb3_probe,
 	.remove		= renesas_usb3_remove,
 	.remove		= renesas_usb3_remove,
 	.driver		= {
 	.driver		= {
 		.name =	(char *)udc_name,
 		.name =	(char *)udc_name,
+		.pm		= &renesas_usb3_pm_ops,
 		.of_match_table = of_match_ptr(usb3_of_match),
 		.of_match_table = of_match_ptr(usb3_of_match),
 	},
 	},
 };
 };

+ 37 - 11
drivers/usb/mtu3/mtu3.h

@@ -46,6 +46,9 @@ struct mtu3_request;
 #define	MU3D_EP_RXCR1(epnum)	(U3D_RX1CSR1 + (((epnum) - 1) * 0x10))
 #define	MU3D_EP_RXCR1(epnum)	(U3D_RX1CSR1 + (((epnum) - 1) * 0x10))
 #define	MU3D_EP_RXCR2(epnum)	(U3D_RX1CSR2 + (((epnum) - 1) * 0x10))
 #define	MU3D_EP_RXCR2(epnum)	(U3D_RX1CSR2 + (((epnum) - 1) * 0x10))
 
 
+#define USB_QMU_TQHIAR(epnum)	(U3D_TXQHIAR1 + (((epnum) - 1) * 0x4))
+#define USB_QMU_RQHIAR(epnum)	(U3D_RXQHIAR1 + (((epnum) - 1) * 0x4))
+
 #define USB_QMU_RQCSR(epnum)	(U3D_RXQCSR1 + (((epnum) - 1) * 0x10))
 #define USB_QMU_RQCSR(epnum)	(U3D_RXQCSR1 + (((epnum) - 1) * 0x10))
 #define USB_QMU_RQSAR(epnum)	(U3D_RXQSAR1 + (((epnum) - 1) * 0x10))
 #define USB_QMU_RQSAR(epnum)	(U3D_RXQSAR1 + (((epnum) - 1) * 0x10))
 #define USB_QMU_RQCPR(epnum)	(U3D_RXQCPR1 + (((epnum) - 1) * 0x10))
 #define USB_QMU_RQCPR(epnum)	(U3D_RXQCPR1 + (((epnum) - 1) * 0x10))
@@ -91,6 +94,7 @@ enum mtu3_speed {
 	MTU3_SPEED_FULL = 1,
 	MTU3_SPEED_FULL = 1,
 	MTU3_SPEED_HIGH = 3,
 	MTU3_SPEED_HIGH = 3,
 	MTU3_SPEED_SUPER = 4,
 	MTU3_SPEED_SUPER = 4,
+	MTU3_SPEED_SUPER_PLUS = 5,
 };
 };
 
 
 /**
 /**
@@ -111,6 +115,19 @@ enum mtu3_g_ep0_state {
 	MU3D_EP0_STATE_STALL,
 	MU3D_EP0_STATE_STALL,
 };
 };
 
 
+/**
+ * MTU3_DR_FORCE_NONE: automatically switch host and periperal mode
+ *		by IDPIN signal.
+ * MTU3_DR_FORCE_HOST: force to enter host mode and override OTG
+ *		IDPIN signal.
+ * MTU3_DR_FORCE_DEVICE: force to enter peripheral mode.
+ */
+enum mtu3_dr_force_mode {
+	MTU3_DR_FORCE_NONE = 0,
+	MTU3_DR_FORCE_HOST,
+	MTU3_DR_FORCE_DEVICE,
+};
+
 /**
 /**
  * @base: the base address of fifo
  * @base: the base address of fifo
  * @limit: the bitmap size in bits
  * @limit: the bitmap size in bits
@@ -138,23 +155,33 @@ struct mtu3_fifo_info {
  *	Checksum value is calculated over the 16 bytes of the GPD by default;
  *	Checksum value is calculated over the 16 bytes of the GPD by default;
  * @data_buf_len (RX ONLY): This value indicates the length of
  * @data_buf_len (RX ONLY): This value indicates the length of
  *	the assigned data buffer
  *	the assigned data buffer
+ * @tx_ext_addr (TX ONLY): [3:0] are 4 extension bits of @buffer,
+ *	[7:4] are 4 extension bits of @next_gpd
  * @next_gpd: Physical address of the next GPD
  * @next_gpd: Physical address of the next GPD
  * @buffer: Physical address of the data buffer
  * @buffer: Physical address of the data buffer
  * @buf_len:
  * @buf_len:
  *	(TX): This value indicates the length of the assigned data buffer
  *	(TX): This value indicates the length of the assigned data buffer
  *	(RX): The total length of data received
  *	(RX): The total length of data received
  * @ext_len: reserved
  * @ext_len: reserved
+ * @rx_ext_addr(RX ONLY): [3:0] are 4 extension bits of @buffer,
+ *	[7:4] are 4 extension bits of @next_gpd
  * @ext_flag:
  * @ext_flag:
  *	bit5 (TX ONLY): Zero Length Packet (ZLP),
  *	bit5 (TX ONLY): Zero Length Packet (ZLP),
  */
  */
 struct qmu_gpd {
 struct qmu_gpd {
 	__u8 flag;
 	__u8 flag;
 	__u8 chksum;
 	__u8 chksum;
-	__le16 data_buf_len;
+	union {
+		__le16 data_buf_len;
+		__le16 tx_ext_addr;
+	};
 	__le32 next_gpd;
 	__le32 next_gpd;
 	__le32 buffer;
 	__le32 buffer;
 	__le16 buf_len;
 	__le16 buf_len;
-	__u8 ext_len;
+	union {
+		__u8 ext_len;
+		__u8 rx_ext_addr;
+	};
 	__u8 ext_flag;
 	__u8 ext_flag;
 } __packed;
 } __packed;
 
 
@@ -183,7 +210,6 @@ struct mtu3_gpd_ring {
 *		xHCI driver initialization, it's necessary for system bootup
 *		xHCI driver initialization, it's necessary for system bootup
 *		as device.
 *		as device.
 * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not
 * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not
-* @id_*: used to maually switch between host and device modes by idpin
 * @manual_drd_enabled: it's true when supports dual-role device by debugfs
 * @manual_drd_enabled: it's true when supports dual-role device by debugfs
 *		to switch host/device modes depending on user input.
 *		to switch host/device modes depending on user input.
 */
 */
@@ -194,10 +220,6 @@ struct otg_switch_mtk {
 	struct notifier_block id_nb;
 	struct notifier_block id_nb;
 	struct delayed_work extcon_reg_dwork;
 	struct delayed_work extcon_reg_dwork;
 	bool is_u3_drd;
 	bool is_u3_drd;
-	/* dual-role switch by debugfs */
-	struct pinctrl *id_pinctrl;
-	struct pinctrl_state *id_float;
-	struct pinctrl_state *id_ground;
 	bool manual_drd_enabled;
 	bool manual_drd_enabled;
 };
 };
 
 
@@ -206,14 +228,17 @@ struct otg_switch_mtk {
  * @ippc_base: register base address of IP Power and Clock interface (IPPC)
  * @ippc_base: register base address of IP Power and Clock interface (IPPC)
  * @vusb33: usb3.3V shared by device/host IP
  * @vusb33: usb3.3V shared by device/host IP
  * @sys_clk: system clock of mtu3, shared by device/host IP
  * @sys_clk: system clock of mtu3, shared by device/host IP
+ * @ref_clk: reference clock
+ * @mcu_clk: mcu_bus_ck clock for AHB bus etc
+ * @dma_clk: dma_bus_ck clock for AXI bus etc
  * @dr_mode: works in which mode:
  * @dr_mode: works in which mode:
  *		host only, device only or dual-role mode
  *		host only, device only or dual-role mode
  * @u2_ports: number of usb2.0 host ports
  * @u2_ports: number of usb2.0 host ports
  * @u3_ports: number of usb3.0 host ports
  * @u3_ports: number of usb3.0 host ports
+ * @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to
+ *		disable u3port0, bit1==1 to disable u3port1,... etc
  * @dbgfs_root: only used when supports manual dual-role switch via debugfs
  * @dbgfs_root: only used when supports manual dual-role switch via debugfs
  * @wakeup_en: it's true when supports remote wakeup in host mode
  * @wakeup_en: it's true when supports remote wakeup in host mode
- * @wk_deb_p0: port0's wakeup debounce clock
- * @wk_deb_p1: it's optional, and depends on port1 is supported or not
  */
  */
 struct ssusb_mtk {
 struct ssusb_mtk {
 	struct device *dev;
 	struct device *dev;
@@ -226,17 +251,18 @@ struct ssusb_mtk {
 	struct regulator *vusb33;
 	struct regulator *vusb33;
 	struct clk *sys_clk;
 	struct clk *sys_clk;
 	struct clk *ref_clk;
 	struct clk *ref_clk;
+	struct clk *mcu_clk;
+	struct clk *dma_clk;
 	/* otg */
 	/* otg */
 	struct otg_switch_mtk otg_switch;
 	struct otg_switch_mtk otg_switch;
 	enum usb_dr_mode dr_mode;
 	enum usb_dr_mode dr_mode;
 	bool is_host;
 	bool is_host;
 	int u2_ports;
 	int u2_ports;
 	int u3_ports;
 	int u3_ports;
+	int u3p_dis_msk;
 	struct dentry *dbgfs_root;
 	struct dentry *dbgfs_root;
 	/* usb wakeup for host mode */
 	/* usb wakeup for host mode */
 	bool wakeup_en;
 	bool wakeup_en;
-	struct clk *wk_deb_p0;
-	struct clk *wk_deb_p1;
 	struct regmap *pericfg;
 	struct regmap *pericfg;
 };
 };
 
 

+ 53 - 8
drivers/usb/mtu3/mtu3_core.c

@@ -17,6 +17,7 @@
  *
  *
  */
  */
 
 
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_address.h>
@@ -114,7 +115,9 @@ static int mtu3_device_enable(struct mtu3 *mtu)
 	mtu3_clrbits(ibase, SSUSB_U2_CTRL(0),
 	mtu3_clrbits(ibase, SSUSB_U2_CTRL(0),
 		(SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN |
 		(SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN |
 		SSUSB_U2_PORT_HOST_SEL));
 		SSUSB_U2_PORT_HOST_SEL));
-	mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL);
+
+	if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG)
+		mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL);
 
 
 	return ssusb_check_clocks(mtu->ssusb, check_clk);
 	return ssusb_check_clocks(mtu->ssusb, check_clk);
 }
 }
@@ -129,7 +132,10 @@ static void mtu3_device_disable(struct mtu3 *mtu)
 
 
 	mtu3_setbits(ibase, SSUSB_U2_CTRL(0),
 	mtu3_setbits(ibase, SSUSB_U2_CTRL(0),
 		SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN);
 		SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN);
-	mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL);
+
+	if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG)
+		mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL);
+
 	mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
 	mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
 }
 }
 
 
@@ -236,7 +242,7 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set)
 
 
 void mtu3_dev_on_off(struct mtu3 *mtu, int is_on)
 void mtu3_dev_on_off(struct mtu3 *mtu, int is_on)
 {
 {
-	if (mtu->is_u3_ip && (mtu->max_speed == USB_SPEED_SUPER))
+	if (mtu->is_u3_ip && mtu->max_speed >= USB_SPEED_SUPER)
 		mtu3_ss_func_set(mtu, is_on);
 		mtu3_ss_func_set(mtu, is_on);
 	else
 	else
 		mtu3_hs_softconn_set(mtu, is_on);
 		mtu3_hs_softconn_set(mtu, is_on);
@@ -546,6 +552,9 @@ static void mtu3_set_speed(struct mtu3 *mtu)
 		mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN);
 		mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN);
 		/* HS/FS detected by HW */
 		/* HS/FS detected by HW */
 		mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE);
 		mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE);
+	} else if (mtu->max_speed == USB_SPEED_SUPER) {
+		mtu3_clrbits(mtu->ippc_base, SSUSB_U3_CTRL(0),
+			     SSUSB_U3_PORT_SSP_SPEED);
 	}
 	}
 
 
 	dev_info(mtu->dev, "max_speed: %s\n",
 	dev_info(mtu->dev, "max_speed: %s\n",
@@ -623,6 +632,10 @@ static irqreturn_t mtu3_link_isr(struct mtu3 *mtu)
 		udev_speed = USB_SPEED_SUPER;
 		udev_speed = USB_SPEED_SUPER;
 		maxpkt = 512;
 		maxpkt = 512;
 		break;
 		break;
+	case MTU3_SPEED_SUPER_PLUS:
+		udev_speed = USB_SPEED_SUPER_PLUS;
+		maxpkt = 512;
+		break;
 	default:
 	default:
 		udev_speed = USB_SPEED_UNKNOWN;
 		udev_speed = USB_SPEED_UNKNOWN;
 		break;
 		break;
@@ -759,7 +772,31 @@ static void mtu3_hw_exit(struct mtu3 *mtu)
 	mtu3_mem_free(mtu);
 	mtu3_mem_free(mtu);
 }
 }
 
 
-/*-------------------------------------------------------------------------*/
+/**
+ * we set 32-bit DMA mask by default, here check whether the controller
+ * supports 36-bit DMA or not, if it does, set 36-bit DMA mask.
+ */
+static int mtu3_set_dma_mask(struct mtu3 *mtu)
+{
+	struct device *dev = mtu->dev;
+	bool is_36bit = false;
+	int ret = 0;
+	u32 value;
+
+	value = mtu3_readl(mtu->mac_base, U3D_MISC_CTRL);
+	if (value & DMA_ADDR_36BIT) {
+		is_36bit = true;
+		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
+		/* If set 36-bit DMA mask fails, fall back to 32-bit DMA mask */
+		if (ret) {
+			is_36bit = false;
+			ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+		}
+	}
+	dev_info(dev, "dma mask: %s bits\n", is_36bit ? "36" : "32");
+
+	return ret;
+}
 
 
 int ssusb_gadget_init(struct ssusb_mtk *ssusb)
 int ssusb_gadget_init(struct ssusb_mtk *ssusb)
 {
 {
@@ -774,9 +811,9 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	mtu->irq = platform_get_irq(pdev, 0);
 	mtu->irq = platform_get_irq(pdev, 0);
-	if (mtu->irq <= 0) {
+	if (mtu->irq < 0) {
 		dev_err(dev, "fail to get irq number\n");
 		dev_err(dev, "fail to get irq number\n");
-		return -ENODEV;
+		return mtu->irq;
 	}
 	}
 	dev_info(dev, "irq %d\n", mtu->irq);
 	dev_info(dev, "irq %d\n", mtu->irq);
 
 
@@ -800,14 +837,15 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb)
 	case USB_SPEED_FULL:
 	case USB_SPEED_FULL:
 	case USB_SPEED_HIGH:
 	case USB_SPEED_HIGH:
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
 		break;
 		break;
 	default:
 	default:
 		dev_err(dev, "invalid max_speed: %s\n",
 		dev_err(dev, "invalid max_speed: %s\n",
 			usb_speed_string(mtu->max_speed));
 			usb_speed_string(mtu->max_speed));
 		/* fall through */
 		/* fall through */
 	case USB_SPEED_UNKNOWN:
 	case USB_SPEED_UNKNOWN:
-		/* default as SS */
-		mtu->max_speed = USB_SPEED_SUPER;
+		/* default as SSP */
+		mtu->max_speed = USB_SPEED_SUPER_PLUS;
 		break;
 		break;
 	}
 	}
 
 
@@ -820,6 +858,12 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb)
 		return ret;
 		return ret;
 	}
 	}
 
 
+	ret = mtu3_set_dma_mask(mtu);
+	if (ret) {
+		dev_err(dev, "mtu3 set dma_mask failed:%d\n", ret);
+		goto dma_mask_err;
+	}
+
 	ret = devm_request_irq(dev, mtu->irq, mtu3_irq, 0, dev_name(dev), mtu);
 	ret = devm_request_irq(dev, mtu->irq, mtu3_irq, 0, dev_name(dev), mtu);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "request irq %d failed!\n", mtu->irq);
 		dev_err(dev, "request irq %d failed!\n", mtu->irq);
@@ -845,6 +889,7 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb)
 gadget_err:
 gadget_err:
 	device_init_wakeup(dev, false);
 	device_init_wakeup(dev, false);
 
 
+dma_mask_err:
 irq_err:
 irq_err:
 	mtu3_hw_exit(mtu);
 	mtu3_hw_exit(mtu);
 	ssusb->u3d = NULL;
 	ssusb->u3d = NULL;

+ 45 - 16
drivers/usb/mtu3/mtu3_dr.c

@@ -261,21 +261,22 @@ static void extcon_register_dwork(struct work_struct *work)
  * depending on user input.
  * depending on user input.
  * This is useful in special cases, such as uses TYPE-A receptacle but also
  * This is useful in special cases, such as uses TYPE-A receptacle but also
  * wants to support dual-role mode.
  * wants to support dual-role mode.
- * It generates cable state changes by pulling up/down IDPIN and
- * notifies driver to switch mode by "extcon-usb-gpio".
- * NOTE: when use MICRO receptacle, should not enable this interface.
  */
  */
 static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host)
 static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host)
 {
 {
 	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
 	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
 
 
-	if (to_host)
-		pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_ground);
-	else
-		pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_float);
+	if (to_host) {
+		ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
+		ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF);
+		ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND);
+	} else {
+		ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE);
+		ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
+		ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
+	}
 }
 }
 
 
-
 static int ssusb_mode_show(struct seq_file *sf, void *unused)
 static int ssusb_mode_show(struct seq_file *sf, void *unused)
 {
 {
 	struct ssusb_mtk *ssusb = sf->private;
 	struct ssusb_mtk *ssusb = sf->private;
@@ -388,17 +389,45 @@ static void ssusb_debugfs_exit(struct ssusb_mtk *ssusb)
 	debugfs_remove_recursive(ssusb->dbgfs_root);
 	debugfs_remove_recursive(ssusb->dbgfs_root);
 }
 }
 
 
+void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
+			  enum mtu3_dr_force_mode mode)
+{
+	u32 value;
+
+	value = mtu3_readl(ssusb->ippc_base, SSUSB_U2_CTRL(0));
+	switch (mode) {
+	case MTU3_DR_FORCE_DEVICE:
+		value |= SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG;
+		break;
+	case MTU3_DR_FORCE_HOST:
+		value |= SSUSB_U2_PORT_FORCE_IDDIG;
+		value &= ~SSUSB_U2_PORT_RG_IDDIG;
+		break;
+	case MTU3_DR_FORCE_NONE:
+		value &= ~(SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG);
+		break;
+	default:
+		return;
+	}
+	mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value);
+}
+
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 {
 {
 	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
 	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
 
 
-	INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, extcon_register_dwork);
-
-	if (otg_sx->manual_drd_enabled)
+	if (otg_sx->manual_drd_enabled) {
 		ssusb_debugfs_init(ssusb);
 		ssusb_debugfs_init(ssusb);
-
-	/* It is enough to delay 1s for waiting for host initialization */
-	schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ);
+	} else {
+		INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork,
+				  extcon_register_dwork);
+
+		/*
+		 * It is enough to delay 1s for waiting for
+		 * host initialization
+		 */
+		schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ);
+	}
 
 
 	return 0;
 	return 0;
 }
 }
@@ -407,8 +436,8 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
 {
 {
 	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
 	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
 
 
-	cancel_delayed_work(&otg_sx->extcon_reg_dwork);
-
 	if (otg_sx->manual_drd_enabled)
 	if (otg_sx->manual_drd_enabled)
 		ssusb_debugfs_exit(ssusb);
 		ssusb_debugfs_exit(ssusb);
+	else
+		cancel_delayed_work(&otg_sx->extcon_reg_dwork);
 }
 }

+ 6 - 0
drivers/usb/mtu3/mtu3_dr.h

@@ -87,6 +87,8 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
 int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
 int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
+void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
+			  enum mtu3_dr_force_mode mode);
 
 
 #else
 #else
 
 
@@ -103,6 +105,10 @@ static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
 	return 0;
 	return 0;
 }
 }
 
 
+static inline void
+ssusb_set_force_mode(struct ssusb_mtk *ssusb, enum mtu3_dr_force_mode mode)
+{}
+
 #endif
 #endif
 
 
 #endif		/* _MTU3_DR_H_ */
 #endif		/* _MTU3_DR_H_ */

+ 2 - 1
drivers/usb/mtu3/mtu3_gadget.c

@@ -89,6 +89,7 @@ static int mtu3_ep_enable(struct mtu3_ep *mep)
 
 
 	switch (mtu->g.speed) {
 	switch (mtu->g.speed) {
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER:
+	case USB_SPEED_SUPER_PLUS:
 		if (usb_endpoint_xfer_int(desc) ||
 		if (usb_endpoint_xfer_int(desc) ||
 				usb_endpoint_xfer_isoc(desc)) {
 				usb_endpoint_xfer_isoc(desc)) {
 			interval = desc->bInterval;
 			interval = desc->bInterval;
@@ -456,7 +457,7 @@ static int mtu3_gadget_wakeup(struct usb_gadget *gadget)
 		return  -EOPNOTSUPP;
 		return  -EOPNOTSUPP;
 
 
 	spin_lock_irqsave(&mtu->lock, flags);
 	spin_lock_irqsave(&mtu->lock, flags);
-	if (mtu->g.speed == USB_SPEED_SUPER) {
+	if (mtu->g.speed >= USB_SPEED_SUPER) {
 		mtu3_setbits(mtu->mac_base, U3D_LINK_POWER_CONTROL, UX_EXIT);
 		mtu3_setbits(mtu->mac_base, U3D_LINK_POWER_CONTROL, UX_EXIT);
 	} else {
 	} else {
 		mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME);
 		mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME);

+ 8 - 8
drivers/usb/mtu3/mtu3_gadget_ep0.c

@@ -212,8 +212,8 @@ ep0_get_status(struct mtu3 *mtu, const struct usb_ctrlrequest *setup)
 	case USB_RECIP_DEVICE:
 	case USB_RECIP_DEVICE:
 		result[0] = mtu->is_self_powered << USB_DEVICE_SELF_POWERED;
 		result[0] = mtu->is_self_powered << USB_DEVICE_SELF_POWERED;
 		result[0] |= mtu->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
 		result[0] |= mtu->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
-		/* superspeed only */
-		if (mtu->g.speed == USB_SPEED_SUPER) {
+
+		if (mtu->g.speed >= USB_SPEED_SUPER) {
 			result[0] |= mtu->u1_enable << USB_DEV_STAT_U1_ENABLED;
 			result[0] |= mtu->u1_enable << USB_DEV_STAT_U1_ENABLED;
 			result[0] |= mtu->u2_enable << USB_DEV_STAT_U2_ENABLED;
 			result[0] |= mtu->u2_enable << USB_DEV_STAT_U2_ENABLED;
 		}
 		}
@@ -329,8 +329,8 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu,
 		handled = handle_test_mode(mtu, setup);
 		handled = handle_test_mode(mtu, setup);
 		break;
 		break;
 	case USB_DEVICE_U1_ENABLE:
 	case USB_DEVICE_U1_ENABLE:
-		if (mtu->g.speed != USB_SPEED_SUPER ||
-			mtu->g.state != USB_STATE_CONFIGURED)
+		if (mtu->g.speed < USB_SPEED_SUPER ||
+		    mtu->g.state != USB_STATE_CONFIGURED)
 			break;
 			break;
 
 
 		lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL);
 		lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL);
@@ -344,8 +344,8 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu,
 		handled = 1;
 		handled = 1;
 		break;
 		break;
 	case USB_DEVICE_U2_ENABLE:
 	case USB_DEVICE_U2_ENABLE:
-		if (mtu->g.speed != USB_SPEED_SUPER ||
-			mtu->g.state != USB_STATE_CONFIGURED)
+		if (mtu->g.speed < USB_SPEED_SUPER ||
+		    mtu->g.state != USB_STATE_CONFIGURED)
 			break;
 			break;
 
 
 		lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL);
 		lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL);
@@ -384,8 +384,8 @@ static int ep0_handle_feature(struct mtu3 *mtu,
 		break;
 		break;
 	case USB_RECIP_INTERFACE:
 	case USB_RECIP_INTERFACE:
 		/* superspeed only */
 		/* superspeed only */
-		if ((value == USB_INTRF_FUNC_SUSPEND)
-			&& (mtu->g.speed == USB_SPEED_SUPER)) {
+		if (value == USB_INTRF_FUNC_SUSPEND &&
+		    mtu->g.speed >= USB_SPEED_SUPER) {
 			/*
 			/*
 			 * forward the request because function drivers
 			 * forward the request because function drivers
 			 * should handle it
 			 * should handle it

+ 22 - 56
drivers/usb/mtu3/mtu3_host.c

@@ -79,20 +79,6 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb,
 	if (!ssusb->wakeup_en)
 	if (!ssusb->wakeup_en)
 		return 0;
 		return 0;
 
 
-	ssusb->wk_deb_p0 = devm_clk_get(dev, "wakeup_deb_p0");
-	if (IS_ERR(ssusb->wk_deb_p0)) {
-		dev_err(dev, "fail to get wakeup_deb_p0\n");
-		return PTR_ERR(ssusb->wk_deb_p0);
-	}
-
-	if (of_property_read_bool(dn, "wakeup_deb_p1")) {
-		ssusb->wk_deb_p1 = devm_clk_get(dev, "wakeup_deb_p1");
-		if (IS_ERR(ssusb->wk_deb_p1)) {
-			dev_err(dev, "fail to get wakeup_deb_p1\n");
-			return PTR_ERR(ssusb->wk_deb_p1);
-		}
-	}
-
 	ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn,
 	ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn,
 						"mediatek,syscon-wakeup");
 						"mediatek,syscon-wakeup");
 	if (IS_ERR(ssusb->pericfg)) {
 	if (IS_ERR(ssusb->pericfg)) {
@@ -103,36 +89,6 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb,
 	return 0;
 	return 0;
 }
 }
 
 
-static int ssusb_wakeup_clks_enable(struct ssusb_mtk *ssusb)
-{
-	int ret;
-
-	ret = clk_prepare_enable(ssusb->wk_deb_p0);
-	if (ret) {
-		dev_err(ssusb->dev, "failed to enable wk_deb_p0\n");
-		goto usb_p0_err;
-	}
-
-	ret = clk_prepare_enable(ssusb->wk_deb_p1);
-	if (ret) {
-		dev_err(ssusb->dev, "failed to enable wk_deb_p1\n");
-		goto usb_p1_err;
-	}
-
-	return 0;
-
-usb_p1_err:
-	clk_disable_unprepare(ssusb->wk_deb_p0);
-usb_p0_err:
-	return -EINVAL;
-}
-
-static void ssusb_wakeup_clks_disable(struct ssusb_mtk *ssusb)
-{
-	clk_disable_unprepare(ssusb->wk_deb_p1);
-	clk_disable_unprepare(ssusb->wk_deb_p0);
-}
-
 static void host_ports_num_get(struct ssusb_mtk *ssusb)
 static void host_ports_num_get(struct ssusb_mtk *ssusb)
 {
 {
 	u32 xhci_cap;
 	u32 xhci_cap;
@@ -151,6 +107,7 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb)
 	void __iomem *ibase = ssusb->ippc_base;
 	void __iomem *ibase = ssusb->ippc_base;
 	int num_u3p = ssusb->u3_ports;
 	int num_u3p = ssusb->u3_ports;
 	int num_u2p = ssusb->u2_ports;
 	int num_u2p = ssusb->u2_ports;
+	int u3_ports_disabed;
 	u32 check_clk;
 	u32 check_clk;
 	u32 value;
 	u32 value;
 	int i;
 	int i;
@@ -158,8 +115,14 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb)
 	/* power on host ip */
 	/* power on host ip */
 	mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN);
 	mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN);
 
 
-	/* power on and enable all u3 ports */
+	/* power on and enable u3 ports except skipped ones */
+	u3_ports_disabed = 0;
 	for (i = 0; i < num_u3p; i++) {
 	for (i = 0; i < num_u3p; i++) {
+		if ((0x1 << i) & ssusb->u3p_dis_msk) {
+			u3_ports_disabed++;
+			continue;
+		}
+
 		value = mtu3_readl(ibase, SSUSB_U3_CTRL(i));
 		value = mtu3_readl(ibase, SSUSB_U3_CTRL(i));
 		value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS);
 		value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS);
 		value |= SSUSB_U3_PORT_HOST_SEL;
 		value |= SSUSB_U3_PORT_HOST_SEL;
@@ -175,7 +138,7 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb)
 	}
 	}
 
 
 	check_clk = SSUSB_XHCI_RST_B_STS;
 	check_clk = SSUSB_XHCI_RST_B_STS;
-	if (num_u3p)
+	if (num_u3p > u3_ports_disabed)
 		check_clk = SSUSB_U3_MAC_RST_B_STS;
 		check_clk = SSUSB_U3_MAC_RST_B_STS;
 
 
 	return ssusb_check_clocks(ssusb, check_clk);
 	return ssusb_check_clocks(ssusb, check_clk);
@@ -190,8 +153,11 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend)
 	int ret;
 	int ret;
 	int i;
 	int i;
 
 
-	/* power down and disable all u3 ports */
+	/* power down and disable u3 ports except skipped ones */
 	for (i = 0; i < num_u3p; i++) {
 	for (i = 0; i < num_u3p; i++) {
+		if ((0x1 << i) & ssusb->u3p_dis_msk)
+			continue;
+
 		value = mtu3_readl(ibase, SSUSB_U3_CTRL(i));
 		value = mtu3_readl(ibase, SSUSB_U3_CTRL(i));
 		value |= SSUSB_U3_PORT_PDN;
 		value |= SSUSB_U3_PORT_PDN;
 		value |= suspend ? 0 : SSUSB_U3_PORT_DIS;
 		value |= suspend ? 0 : SSUSB_U3_PORT_DIS;
@@ -223,6 +189,8 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend)
 
 
 static void ssusb_host_setup(struct ssusb_mtk *ssusb)
 static void ssusb_host_setup(struct ssusb_mtk *ssusb)
 {
 {
+	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
+
 	host_ports_num_get(ssusb);
 	host_ports_num_get(ssusb);
 
 
 	/*
 	/*
@@ -231,6 +199,9 @@ static void ssusb_host_setup(struct ssusb_mtk *ssusb)
 	 */
 	 */
 	ssusb_host_enable(ssusb);
 	ssusb_host_enable(ssusb);
 
 
+	if (otg_sx->manual_drd_enabled)
+		ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
+
 	/* if port0 supports dual-role, works as host mode by default */
 	/* if port0 supports dual-role, works as host mode by default */
 	ssusb_set_vbus(&ssusb->otg_switch, 1);
 	ssusb_set_vbus(&ssusb->otg_switch, 1);
 }
 }
@@ -276,19 +247,14 @@ void ssusb_host_exit(struct ssusb_mtk *ssusb)
 
 
 int ssusb_wakeup_enable(struct ssusb_mtk *ssusb)
 int ssusb_wakeup_enable(struct ssusb_mtk *ssusb)
 {
 {
-	int ret = 0;
-
-	if (ssusb->wakeup_en) {
-		ret = ssusb_wakeup_clks_enable(ssusb);
+	if (ssusb->wakeup_en)
 		ssusb_wakeup_ip_sleep_en(ssusb);
 		ssusb_wakeup_ip_sleep_en(ssusb);
-	}
-	return ret;
+
+	return 0;
 }
 }
 
 
 void ssusb_wakeup_disable(struct ssusb_mtk *ssusb)
 void ssusb_wakeup_disable(struct ssusb_mtk *ssusb)
 {
 {
-	if (ssusb->wakeup_en) {
+	if (ssusb->wakeup_en)
 		ssusb_wakeup_ip_sleep_dis(ssusb);
 		ssusb_wakeup_ip_sleep_dis(ssusb);
-		ssusb_wakeup_clks_disable(ssusb);
-	}
 }
 }

+ 13 - 0
drivers/usb/mtu3/mtu3_hw_regs.h

@@ -58,6 +58,8 @@
 #define U3D_QCR1		(SSUSB_DEV_BASE + 0x0404)
 #define U3D_QCR1		(SSUSB_DEV_BASE + 0x0404)
 #define U3D_QCR2		(SSUSB_DEV_BASE + 0x0408)
 #define U3D_QCR2		(SSUSB_DEV_BASE + 0x0408)
 #define U3D_QCR3		(SSUSB_DEV_BASE + 0x040C)
 #define U3D_QCR3		(SSUSB_DEV_BASE + 0x040C)
+#define U3D_TXQHIAR1		(SSUSB_DEV_BASE + 0x0484)
+#define U3D_RXQHIAR1		(SSUSB_DEV_BASE + 0x04C4)
 
 
 #define U3D_TXQCSR1		(SSUSB_DEV_BASE + 0x0510)
 #define U3D_TXQCSR1		(SSUSB_DEV_BASE + 0x0510)
 #define U3D_TXQSAR1		(SSUSB_DEV_BASE + 0x0514)
 #define U3D_TXQSAR1		(SSUSB_DEV_BASE + 0x0514)
@@ -189,6 +191,13 @@
 #define QMU_RX_COZ(x)		(BIT(16) << (x))
 #define QMU_RX_COZ(x)		(BIT(16) << (x))
 #define QMU_RX_ZLP(x)		(BIT(0) << (x))
 #define QMU_RX_ZLP(x)		(BIT(0) << (x))
 
 
+/* U3D_TXQHIAR1 */
+/* U3D_RXQHIAR1 */
+#define QMU_LAST_DONE_PTR_HI(x)	(((x) >> 16) & 0xf)
+#define QMU_CUR_GPD_ADDR_HI(x)	(((x) >> 8) & 0xf)
+#define QMU_START_ADDR_HI_MSK	GENMASK(3, 0)
+#define QMU_START_ADDR_HI(x)	(((x) & 0xf) << 0)
+
 /* U3D_TXQCSR1 */
 /* U3D_TXQCSR1 */
 /* U3D_RXQCSR1 */
 /* U3D_RXQCSR1 */
 #define QMU_Q_ACTIVE		BIT(15)
 #define QMU_Q_ACTIVE		BIT(15)
@@ -225,6 +234,7 @@
 #define CAP_TX_EP_NUM(x)	((x) & 0x1f)
 #define CAP_TX_EP_NUM(x)	((x) & 0x1f)
 
 
 /* U3D_MISC_CTRL */
 /* U3D_MISC_CTRL */
+#define DMA_ADDR_36BIT		BIT(31)
 #define VBUS_ON			BIT(1)
 #define VBUS_ON			BIT(1)
 #define VBUS_FRC_EN		BIT(0)
 #define VBUS_FRC_EN		BIT(0)
 
 
@@ -457,11 +467,14 @@
 #define SSUSB_VBUS_CHG_INT_B_EN		BIT(6)
 #define SSUSB_VBUS_CHG_INT_B_EN		BIT(6)
 
 
 /* U3D_SSUSB_U3_CTRL_0P */
 /* U3D_SSUSB_U3_CTRL_0P */
+#define SSUSB_U3_PORT_SSP_SPEED	BIT(9)
 #define SSUSB_U3_PORT_HOST_SEL		BIT(2)
 #define SSUSB_U3_PORT_HOST_SEL		BIT(2)
 #define SSUSB_U3_PORT_PDN		BIT(1)
 #define SSUSB_U3_PORT_PDN		BIT(1)
 #define SSUSB_U3_PORT_DIS		BIT(0)
 #define SSUSB_U3_PORT_DIS		BIT(0)
 
 
 /* U3D_SSUSB_U2_CTRL_0P */
 /* U3D_SSUSB_U2_CTRL_0P */
+#define SSUSB_U2_PORT_RG_IDDIG		BIT(12)
+#define SSUSB_U2_PORT_FORCE_IDDIG	BIT(11)
 #define SSUSB_U2_PORT_VBUSVALID	BIT(9)
 #define SSUSB_U2_PORT_VBUSVALID	BIT(9)
 #define SSUSB_U2_PORT_OTG_SEL		BIT(7)
 #define SSUSB_U2_PORT_OTG_SEL		BIT(7)
 #define SSUSB_U2_PORT_HOST		BIT(2)
 #define SSUSB_U2_PORT_HOST		BIT(2)

+ 88 - 77
drivers/usb/mtu3/mtu3_plat.c

@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_irq.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 
 
 #include "mtu3.h"
 #include "mtu3.h"
@@ -110,15 +109,9 @@ static void ssusb_phy_power_off(struct ssusb_mtk *ssusb)
 		phy_power_off(ssusb->phys[i]);
 		phy_power_off(ssusb->phys[i]);
 }
 }
 
 
-static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
+static int ssusb_clks_enable(struct ssusb_mtk *ssusb)
 {
 {
-	int ret = 0;
-
-	ret = regulator_enable(ssusb->vusb33);
-	if (ret) {
-		dev_err(ssusb->dev, "failed to enable vusb33\n");
-		goto vusb33_err;
-	}
+	int ret;
 
 
 	ret = clk_prepare_enable(ssusb->sys_clk);
 	ret = clk_prepare_enable(ssusb->sys_clk);
 	if (ret) {
 	if (ret) {
@@ -132,6 +125,52 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
 		goto ref_clk_err;
 		goto ref_clk_err;
 	}
 	}
 
 
+	ret = clk_prepare_enable(ssusb->mcu_clk);
+	if (ret) {
+		dev_err(ssusb->dev, "failed to enable mcu_clk\n");
+		goto mcu_clk_err;
+	}
+
+	ret = clk_prepare_enable(ssusb->dma_clk);
+	if (ret) {
+		dev_err(ssusb->dev, "failed to enable dma_clk\n");
+		goto dma_clk_err;
+	}
+
+	return 0;
+
+dma_clk_err:
+	clk_disable_unprepare(ssusb->mcu_clk);
+mcu_clk_err:
+	clk_disable_unprepare(ssusb->ref_clk);
+ref_clk_err:
+	clk_disable_unprepare(ssusb->sys_clk);
+sys_clk_err:
+	return ret;
+}
+
+static void ssusb_clks_disable(struct ssusb_mtk *ssusb)
+{
+	clk_disable_unprepare(ssusb->dma_clk);
+	clk_disable_unprepare(ssusb->mcu_clk);
+	clk_disable_unprepare(ssusb->ref_clk);
+	clk_disable_unprepare(ssusb->sys_clk);
+}
+
+static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
+{
+	int ret = 0;
+
+	ret = regulator_enable(ssusb->vusb33);
+	if (ret) {
+		dev_err(ssusb->dev, "failed to enable vusb33\n");
+		goto vusb33_err;
+	}
+
+	ret = ssusb_clks_enable(ssusb);
+	if (ret)
+		goto clks_err;
+
 	ret = ssusb_phy_init(ssusb);
 	ret = ssusb_phy_init(ssusb);
 	if (ret) {
 	if (ret) {
 		dev_err(ssusb->dev, "failed to init phy\n");
 		dev_err(ssusb->dev, "failed to init phy\n");
@@ -149,20 +188,16 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
 phy_err:
 phy_err:
 	ssusb_phy_exit(ssusb);
 	ssusb_phy_exit(ssusb);
 phy_init_err:
 phy_init_err:
-	clk_disable_unprepare(ssusb->ref_clk);
-ref_clk_err:
-	clk_disable_unprepare(ssusb->sys_clk);
-sys_clk_err:
+	ssusb_clks_disable(ssusb);
+clks_err:
 	regulator_disable(ssusb->vusb33);
 	regulator_disable(ssusb->vusb33);
 vusb33_err:
 vusb33_err:
-
 	return ret;
 	return ret;
 }
 }
 
 
 static void ssusb_rscs_exit(struct ssusb_mtk *ssusb)
 static void ssusb_rscs_exit(struct ssusb_mtk *ssusb)
 {
 {
-	clk_disable_unprepare(ssusb->sys_clk);
-	clk_disable_unprepare(ssusb->ref_clk);
+	ssusb_clks_disable(ssusb);
 	regulator_disable(ssusb->vusb33);
 	regulator_disable(ssusb->vusb33);
 	ssusb_phy_power_off(ssusb);
 	ssusb_phy_power_off(ssusb);
 	ssusb_phy_exit(ssusb);
 	ssusb_phy_exit(ssusb);
@@ -176,31 +211,17 @@ static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb)
 	mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST);
 	mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST);
 }
 }
 
 
-static int get_iddig_pinctrl(struct ssusb_mtk *ssusb)
+/* ignore the error if the clock does not exist */
+static struct clk *get_optional_clk(struct device *dev, const char *id)
 {
 {
-	struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
+	struct clk *opt_clk;
 
 
-	otg_sx->id_pinctrl = devm_pinctrl_get(ssusb->dev);
-	if (IS_ERR(otg_sx->id_pinctrl)) {
-		dev_err(ssusb->dev, "Cannot find id pinctrl!\n");
-		return PTR_ERR(otg_sx->id_pinctrl);
-	}
+	opt_clk = devm_clk_get(dev, id);
+	/* ignore error number except EPROBE_DEFER */
+	if (IS_ERR(opt_clk) && (PTR_ERR(opt_clk) != -EPROBE_DEFER))
+		opt_clk = NULL;
 
 
-	otg_sx->id_float =
-		pinctrl_lookup_state(otg_sx->id_pinctrl, "id_float");
-	if (IS_ERR(otg_sx->id_float)) {
-		dev_err(ssusb->dev, "Cannot find pinctrl id_float!\n");
-		return PTR_ERR(otg_sx->id_float);
-	}
-
-	otg_sx->id_ground =
-		pinctrl_lookup_state(otg_sx->id_pinctrl, "id_ground");
-	if (IS_ERR(otg_sx->id_ground)) {
-		dev_err(ssusb->dev, "Cannot find pinctrl id_ground!\n");
-		return PTR_ERR(otg_sx->id_ground);
-	}
-
-	return 0;
+	return opt_clk;
 }
 }
 
 
 static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
@@ -225,18 +246,17 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 		return PTR_ERR(ssusb->sys_clk);
 		return PTR_ERR(ssusb->sys_clk);
 	}
 	}
 
 
-	/*
-	 * reference clock is usually a "fixed-clock", make it optional
-	 * for backward compatibility and ignore the error if it does
-	 * not exist.
-	 */
-	ssusb->ref_clk = devm_clk_get(dev, "ref_ck");
-	if (IS_ERR(ssusb->ref_clk)) {
-		if (PTR_ERR(ssusb->ref_clk) == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
+	ssusb->ref_clk = get_optional_clk(dev, "ref_ck");
+	if (IS_ERR(ssusb->ref_clk))
+		return PTR_ERR(ssusb->ref_clk);
 
 
-		ssusb->ref_clk = NULL;
-	}
+	ssusb->mcu_clk = get_optional_clk(dev, "mcu_ck");
+	if (IS_ERR(ssusb->mcu_clk))
+		return PTR_ERR(ssusb->mcu_clk);
+
+	ssusb->dma_clk = get_optional_clk(dev, "dma_ck");
+	if (IS_ERR(ssusb->dma_clk))
+		return PTR_ERR(ssusb->dma_clk);
 
 
 	ssusb->num_phys = of_count_phandle_with_args(node,
 	ssusb->num_phys = of_count_phandle_with_args(node,
 			"phys", "#phy-cells");
 			"phys", "#phy-cells");
@@ -263,10 +283,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 		return PTR_ERR(ssusb->ippc_base);
 		return PTR_ERR(ssusb->ippc_base);
 
 
 	ssusb->dr_mode = usb_get_dr_mode(dev);
 	ssusb->dr_mode = usb_get_dr_mode(dev);
-	if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN) {
-		dev_err(dev, "dr_mode is error\n");
-		return -EINVAL;
-	}
+	if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN)
+		ssusb->dr_mode = USB_DR_MODE_OTG;
 
 
 	if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL)
 	if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL)
 		return 0;
 		return 0;
@@ -276,10 +294,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	if (ssusb->dr_mode != USB_DR_MODE_OTG)
-		return 0;
+	/* optional property, ignore the error if it does not exist */
+	of_property_read_u32(node, "mediatek,u3p-dis-msk",
+			     &ssusb->u3p_dis_msk);
 
 
-	/* if dual-role mode is supported */
 	vbus = devm_regulator_get(&pdev->dev, "vbus");
 	vbus = devm_regulator_get(&pdev->dev, "vbus");
 	if (IS_ERR(vbus)) {
 	if (IS_ERR(vbus)) {
 		dev_err(dev, "failed to get vbus\n");
 		dev_err(dev, "failed to get vbus\n");
@@ -287,6 +305,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 	}
 	}
 	otg_sx->vbus = vbus;
 	otg_sx->vbus = vbus;
 
 
+	if (ssusb->dr_mode == USB_DR_MODE_HOST)
+		return 0;
+
+	/* if dual-role mode is supported */
 	otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
 	otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
 	otg_sx->manual_drd_enabled =
 	otg_sx->manual_drd_enabled =
 		of_property_read_bool(node, "enable-manual-drd");
 		of_property_read_bool(node, "enable-manual-drd");
@@ -297,15 +319,11 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 			dev_err(ssusb->dev, "couldn't get extcon device\n");
 			dev_err(ssusb->dev, "couldn't get extcon device\n");
 			return -EPROBE_DEFER;
 			return -EPROBE_DEFER;
 		}
 		}
-		if (otg_sx->manual_drd_enabled) {
-			ret = get_iddig_pinctrl(ssusb);
-			if (ret)
-				return ret;
-		}
 	}
 	}
 
 
-	dev_info(dev, "dr_mode: %d, is_u3_dr: %d\n",
-		ssusb->dr_mode, otg_sx->is_u3_drd);
+	dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk: %x, drd: %s\n",
+		ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk,
+		otg_sx->manual_drd_enabled ? "manual" : "auto");
 
 
 	return 0;
 	return 0;
 }
 }
@@ -447,8 +465,7 @@ static int __maybe_unused mtu3_suspend(struct device *dev)
 
 
 	ssusb_host_disable(ssusb, true);
 	ssusb_host_disable(ssusb, true);
 	ssusb_phy_power_off(ssusb);
 	ssusb_phy_power_off(ssusb);
-	clk_disable_unprepare(ssusb->sys_clk);
-	clk_disable_unprepare(ssusb->ref_clk);
+	ssusb_clks_disable(ssusb);
 	ssusb_wakeup_enable(ssusb);
 	ssusb_wakeup_enable(ssusb);
 
 
 	return 0;
 	return 0;
@@ -466,27 +483,21 @@ static int __maybe_unused mtu3_resume(struct device *dev)
 		return 0;
 		return 0;
 
 
 	ssusb_wakeup_disable(ssusb);
 	ssusb_wakeup_disable(ssusb);
-	ret = clk_prepare_enable(ssusb->sys_clk);
-	if (ret)
-		goto err_sys_clk;
-
-	ret = clk_prepare_enable(ssusb->ref_clk);
+	ret = ssusb_clks_enable(ssusb);
 	if (ret)
 	if (ret)
-		goto err_ref_clk;
+		goto clks_err;
 
 
 	ret = ssusb_phy_power_on(ssusb);
 	ret = ssusb_phy_power_on(ssusb);
 	if (ret)
 	if (ret)
-		goto err_power_on;
+		goto phy_err;
 
 
 	ssusb_host_enable(ssusb);
 	ssusb_host_enable(ssusb);
 
 
 	return 0;
 	return 0;
 
 
-err_power_on:
-	clk_disable_unprepare(ssusb->ref_clk);
-err_ref_clk:
-	clk_disable_unprepare(ssusb->sys_clk);
-err_sys_clk:
+phy_err:
+	ssusb_clks_disable(ssusb);
+clks_err:
 	return ret;
 	return ret;
 }
 }
 
 

+ 84 - 18
drivers/usb/mtu3/mtu3_qmu.c

@@ -40,7 +40,58 @@
 #define GPD_FLAGS_IOC	BIT(7)
 #define GPD_FLAGS_IOC	BIT(7)
 
 
 #define GPD_EXT_FLAG_ZLP	BIT(5)
 #define GPD_EXT_FLAG_ZLP	BIT(5)
+#define GPD_EXT_NGP(x)		(((x) & 0xf) << 4)
+#define GPD_EXT_BUF(x)		(((x) & 0xf) << 0)
 
 
+#define HILO_GEN64(hi, lo) (((u64)(hi) << 32) + (lo))
+#define HILO_DMA(hi, lo)	\
+	((dma_addr_t)HILO_GEN64((le32_to_cpu(hi)), (le32_to_cpu(lo))))
+
+static dma_addr_t read_txq_cur_addr(void __iomem *mbase, u8 epnum)
+{
+	u32 txcpr;
+	u32 txhiar;
+
+	txcpr = mtu3_readl(mbase, USB_QMU_TQCPR(epnum));
+	txhiar = mtu3_readl(mbase, USB_QMU_TQHIAR(epnum));
+
+	return HILO_DMA(QMU_CUR_GPD_ADDR_HI(txhiar), txcpr);
+}
+
+static dma_addr_t read_rxq_cur_addr(void __iomem *mbase, u8 epnum)
+{
+	u32 rxcpr;
+	u32 rxhiar;
+
+	rxcpr = mtu3_readl(mbase, USB_QMU_RQCPR(epnum));
+	rxhiar = mtu3_readl(mbase, USB_QMU_RQHIAR(epnum));
+
+	return HILO_DMA(QMU_CUR_GPD_ADDR_HI(rxhiar), rxcpr);
+}
+
+static void write_txq_start_addr(void __iomem *mbase, u8 epnum, dma_addr_t dma)
+{
+	u32 tqhiar;
+
+	mtu3_writel(mbase, USB_QMU_TQSAR(epnum),
+		    cpu_to_le32(lower_32_bits(dma)));
+	tqhiar = mtu3_readl(mbase, USB_QMU_TQHIAR(epnum));
+	tqhiar &= ~QMU_START_ADDR_HI_MSK;
+	tqhiar |= QMU_START_ADDR_HI(upper_32_bits(dma));
+	mtu3_writel(mbase, USB_QMU_TQHIAR(epnum), tqhiar);
+}
+
+static void write_rxq_start_addr(void __iomem *mbase, u8 epnum, dma_addr_t dma)
+{
+	u32 rqhiar;
+
+	mtu3_writel(mbase, USB_QMU_RQSAR(epnum),
+		    cpu_to_le32(lower_32_bits(dma)));
+	rqhiar = mtu3_readl(mbase, USB_QMU_RQHIAR(epnum));
+	rqhiar &= ~QMU_START_ADDR_HI_MSK;
+	rqhiar |= QMU_START_ADDR_HI(upper_32_bits(dma));
+	mtu3_writel(mbase, USB_QMU_RQHIAR(epnum), rqhiar);
+}
 
 
 static struct qmu_gpd *gpd_dma_to_virt(struct mtu3_gpd_ring *ring,
 static struct qmu_gpd *gpd_dma_to_virt(struct mtu3_gpd_ring *ring,
 		dma_addr_t dma_addr)
 		dma_addr_t dma_addr)
@@ -193,21 +244,27 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq)
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 	struct qmu_gpd *gpd = ring->enqueue;
 	struct qmu_gpd *gpd = ring->enqueue;
 	struct usb_request *req = &mreq->request;
 	struct usb_request *req = &mreq->request;
+	dma_addr_t enq_dma;
+	u16 ext_addr;
 
 
 	/* set all fields to zero as default value */
 	/* set all fields to zero as default value */
 	memset(gpd, 0, sizeof(*gpd));
 	memset(gpd, 0, sizeof(*gpd));
 
 
-	gpd->buffer = cpu_to_le32((u32)req->dma);
+	gpd->buffer = cpu_to_le32(lower_32_bits(req->dma));
+	ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma));
 	gpd->buf_len = cpu_to_le16(req->length);
 	gpd->buf_len = cpu_to_le16(req->length);
 	gpd->flag |= GPD_FLAGS_IOC;
 	gpd->flag |= GPD_FLAGS_IOC;
 
 
 	/* get the next GPD */
 	/* get the next GPD */
 	enq = advance_enq_gpd(ring);
 	enq = advance_enq_gpd(ring);
-	dev_dbg(mep->mtu->dev, "TX-EP%d queue gpd=%p, enq=%p\n",
-		mep->epnum, gpd, enq);
+	enq_dma = gpd_virt_to_dma(ring, enq);
+	dev_dbg(mep->mtu->dev, "TX-EP%d queue gpd=%p, enq=%p, qdma=%pad\n",
+		mep->epnum, gpd, enq, enq_dma);
 
 
 	enq->flag &= ~GPD_FLAGS_HWO;
 	enq->flag &= ~GPD_FLAGS_HWO;
-	gpd->next_gpd = cpu_to_le32((u32)gpd_virt_to_dma(ring, enq));
+	gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma));
+	ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma));
+	gpd->tx_ext_addr = cpu_to_le16(ext_addr);
 
 
 	if (req->zero)
 	if (req->zero)
 		gpd->ext_flag |= GPD_EXT_FLAG_ZLP;
 		gpd->ext_flag |= GPD_EXT_FLAG_ZLP;
@@ -226,21 +283,27 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq)
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 	struct qmu_gpd *gpd = ring->enqueue;
 	struct qmu_gpd *gpd = ring->enqueue;
 	struct usb_request *req = &mreq->request;
 	struct usb_request *req = &mreq->request;
+	dma_addr_t enq_dma;
+	u16 ext_addr;
 
 
 	/* set all fields to zero as default value */
 	/* set all fields to zero as default value */
 	memset(gpd, 0, sizeof(*gpd));
 	memset(gpd, 0, sizeof(*gpd));
 
 
-	gpd->buffer = cpu_to_le32((u32)req->dma);
+	gpd->buffer = cpu_to_le32(lower_32_bits(req->dma));
+	ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma));
 	gpd->data_buf_len = cpu_to_le16(req->length);
 	gpd->data_buf_len = cpu_to_le16(req->length);
 	gpd->flag |= GPD_FLAGS_IOC;
 	gpd->flag |= GPD_FLAGS_IOC;
 
 
 	/* get the next GPD */
 	/* get the next GPD */
 	enq = advance_enq_gpd(ring);
 	enq = advance_enq_gpd(ring);
-	dev_dbg(mep->mtu->dev, "RX-EP%d queue gpd=%p, enq=%p\n",
-		mep->epnum, gpd, enq);
+	enq_dma = gpd_virt_to_dma(ring, enq);
+	dev_dbg(mep->mtu->dev, "RX-EP%d queue gpd=%p, enq=%p, qdma=%pad\n",
+		mep->epnum, gpd, enq, enq_dma);
 
 
 	enq->flag &= ~GPD_FLAGS_HWO;
 	enq->flag &= ~GPD_FLAGS_HWO;
-	gpd->next_gpd = cpu_to_le32((u32)gpd_virt_to_dma(ring, enq));
+	gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma));
+	ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma));
+	gpd->rx_ext_addr = cpu_to_le16(ext_addr);
 	gpd->chksum = qmu_calc_checksum((u8 *)gpd);
 	gpd->chksum = qmu_calc_checksum((u8 *)gpd);
 	gpd->flag |= GPD_FLAGS_HWO;
 	gpd->flag |= GPD_FLAGS_HWO;
 
 
@@ -267,8 +330,8 @@ int mtu3_qmu_start(struct mtu3_ep *mep)
 
 
 	if (mep->is_in) {
 	if (mep->is_in) {
 		/* set QMU start address */
 		/* set QMU start address */
-		mtu3_writel(mbase, USB_QMU_TQSAR(mep->epnum), ring->dma);
-		mtu3_setbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN);
+		write_txq_start_addr(mbase, epnum, ring->dma);
+		mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_DMAREQEN);
 		mtu3_setbits(mbase, U3D_QCR0, QMU_TX_CS_EN(epnum));
 		mtu3_setbits(mbase, U3D_QCR0, QMU_TX_CS_EN(epnum));
 		/* send zero length packet according to ZLP flag in GPD */
 		/* send zero length packet according to ZLP flag in GPD */
 		mtu3_setbits(mbase, U3D_QCR1, QMU_TX_ZLP(epnum));
 		mtu3_setbits(mbase, U3D_QCR1, QMU_TX_ZLP(epnum));
@@ -282,8 +345,8 @@ int mtu3_qmu_start(struct mtu3_ep *mep)
 		mtu3_writel(mbase, USB_QMU_TQCSR(epnum), QMU_Q_START);
 		mtu3_writel(mbase, USB_QMU_TQCSR(epnum), QMU_Q_START);
 
 
 	} else {
 	} else {
-		mtu3_writel(mbase, USB_QMU_RQSAR(mep->epnum), ring->dma);
-		mtu3_setbits(mbase, MU3D_EP_RXCR0(mep->epnum), RX_DMAREQEN);
+		write_rxq_start_addr(mbase, epnum, ring->dma);
+		mtu3_setbits(mbase, MU3D_EP_RXCR0(epnum), RX_DMAREQEN);
 		mtu3_setbits(mbase, U3D_QCR0, QMU_RX_CS_EN(epnum));
 		mtu3_setbits(mbase, U3D_QCR0, QMU_RX_CS_EN(epnum));
 		/* don't expect ZLP */
 		/* don't expect ZLP */
 		mtu3_clrbits(mbase, U3D_QCR3, QMU_RX_ZLP(epnum));
 		mtu3_clrbits(mbase, U3D_QCR3, QMU_RX_ZLP(epnum));
@@ -353,9 +416,9 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum)
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 	struct mtu3_gpd_ring *ring = &mep->gpd_ring;
 	void __iomem *mbase = mtu->mac_base;
 	void __iomem *mbase = mtu->mac_base;
 	struct qmu_gpd *gpd_current = NULL;
 	struct qmu_gpd *gpd_current = NULL;
-	dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_TQCPR(epnum));
 	struct usb_request *req = NULL;
 	struct usb_request *req = NULL;
 	struct mtu3_request *mreq;
 	struct mtu3_request *mreq;
+	dma_addr_t cur_gpd_dma;
 	u32 txcsr = 0;
 	u32 txcsr = 0;
 	int ret;
 	int ret;
 
 
@@ -365,7 +428,8 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum)
 	else
 	else
 		return;
 		return;
 
 
-	gpd_current = gpd_dma_to_virt(ring, gpd_dma);
+	cur_gpd_dma = read_txq_cur_addr(mbase, epnum);
+	gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma);
 
 
 	if (le16_to_cpu(gpd_current->buf_len) != 0) {
 	if (le16_to_cpu(gpd_current->buf_len) != 0) {
 		dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum);
 		dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum);
@@ -408,12 +472,13 @@ static void qmu_done_tx(struct mtu3 *mtu, u8 epnum)
 	void __iomem *mbase = mtu->mac_base;
 	void __iomem *mbase = mtu->mac_base;
 	struct qmu_gpd *gpd = ring->dequeue;
 	struct qmu_gpd *gpd = ring->dequeue;
 	struct qmu_gpd *gpd_current = NULL;
 	struct qmu_gpd *gpd_current = NULL;
-	dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_TQCPR(epnum));
 	struct usb_request *request = NULL;
 	struct usb_request *request = NULL;
 	struct mtu3_request *mreq;
 	struct mtu3_request *mreq;
+	dma_addr_t cur_gpd_dma;
 
 
 	/*transfer phy address got from QMU register to virtual address */
 	/*transfer phy address got from QMU register to virtual address */
-	gpd_current = gpd_dma_to_virt(ring, gpd_dma);
+	cur_gpd_dma = read_txq_cur_addr(mbase, epnum);
+	gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma);
 
 
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 		__func__, epnum, gpd, gpd_current, ring->enqueue);
 		__func__, epnum, gpd, gpd_current, ring->enqueue);
@@ -446,11 +511,12 @@ static void qmu_done_rx(struct mtu3 *mtu, u8 epnum)
 	void __iomem *mbase = mtu->mac_base;
 	void __iomem *mbase = mtu->mac_base;
 	struct qmu_gpd *gpd = ring->dequeue;
 	struct qmu_gpd *gpd = ring->dequeue;
 	struct qmu_gpd *gpd_current = NULL;
 	struct qmu_gpd *gpd_current = NULL;
-	dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_RQCPR(epnum));
 	struct usb_request *req = NULL;
 	struct usb_request *req = NULL;
 	struct mtu3_request *mreq;
 	struct mtu3_request *mreq;
+	dma_addr_t cur_gpd_dma;
 
 
-	gpd_current = gpd_dma_to_virt(ring, gpd_dma);
+	cur_gpd_dma = read_rxq_cur_addr(mbase, epnum);
+	gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma);
 
 
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 		__func__, epnum, gpd, gpd_current, ring->enqueue);
 		__func__, epnum, gpd, gpd_current, ring->enqueue);

+ 4 - 1
drivers/usb/phy/phy-generic.c

@@ -224,7 +224,7 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
 	int err = 0;
 	int err = 0;
 
 
 	u32 clk_rate = 0;
 	u32 clk_rate = 0;
-	bool needs_vcc = false;
+	bool needs_vcc = false, needs_clk = false;
 
 
 	if (dev->of_node) {
 	if (dev->of_node) {
 		struct device_node *node = dev->of_node;
 		struct device_node *node = dev->of_node;
@@ -233,6 +233,7 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
 			clk_rate = 0;
 			clk_rate = 0;
 
 
 		needs_vcc = of_property_read_bool(node, "vcc-supply");
 		needs_vcc = of_property_read_bool(node, "vcc-supply");
+		needs_clk = of_property_read_bool(node, "clocks");
 		nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
 		nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
 							   GPIOD_ASIS);
 							   GPIOD_ASIS);
 		err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
 		err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
@@ -275,6 +276,8 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
 	if (IS_ERR(nop->clk)) {
 	if (IS_ERR(nop->clk)) {
 		dev_dbg(dev, "Can't get phy clock: %ld\n",
 		dev_dbg(dev, "Can't get phy clock: %ld\n",
 					PTR_ERR(nop->clk));
 					PTR_ERR(nop->clk));
+		if (needs_clk)
+			return PTR_ERR(nop->clk);
 	}
 	}
 
 
 	if (!IS_ERR(nop->clk) && clk_rate) {
 	if (!IS_ERR(nop->clk) && clk_rate) {

+ 1 - 0
drivers/usb/phy/phy-msm-usb.c

@@ -1261,6 +1261,7 @@ static void msm_chg_detect_work(struct work_struct *w)
 		/* fall through */
 		/* fall through */
 	case USB_CHG_STATE_SECONDARY_DONE:
 	case USB_CHG_STATE_SECONDARY_DONE:
 		motg->chg_state = USB_CHG_STATE_DETECTED;
 		motg->chg_state = USB_CHG_STATE_DETECTED;
+		/* fall through */
 	case USB_CHG_STATE_DETECTED:
 	case USB_CHG_STATE_DETECTED:
 		msm_chg_block_off(motg);
 		msm_chg_block_off(motg);
 		dev_dbg(phy->dev, "charger = %d\n", motg->chg_type);
 		dev_dbg(phy->dev, "charger = %d\n", motg->chg_type);

+ 154 - 0
drivers/usb/phy/phy-mxs-usb.c

@@ -67,11 +67,26 @@
 #define ANADIG_ANA_MISC0_SET			0x154
 #define ANADIG_ANA_MISC0_SET			0x154
 #define ANADIG_ANA_MISC0_CLR			0x158
 #define ANADIG_ANA_MISC0_CLR			0x158
 
 
+#define ANADIG_USB1_CHRG_DETECT_SET		0x1b4
+#define ANADIG_USB1_CHRG_DETECT_CLR		0x1b8
+#define ANADIG_USB1_CHRG_DETECT_EN_B		BIT(20)
+#define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B	BIT(19)
+#define ANADIG_USB1_CHRG_DETECT_CHK_CONTACT	BIT(18)
+
 #define ANADIG_USB1_VBUS_DET_STAT		0x1c0
 #define ANADIG_USB1_VBUS_DET_STAT		0x1c0
+#define ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID	BIT(3)
+
+#define ANADIG_USB1_CHRG_DET_STAT		0x1d0
+#define ANADIG_USB1_CHRG_DET_STAT_DM_STATE	BIT(2)
+#define ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED	BIT(1)
+#define ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT	BIT(0)
+
 #define ANADIG_USB2_VBUS_DET_STAT		0x220
 #define ANADIG_USB2_VBUS_DET_STAT		0x220
 
 
 #define ANADIG_USB1_LOOPBACK_SET		0x1e4
 #define ANADIG_USB1_LOOPBACK_SET		0x1e4
 #define ANADIG_USB1_LOOPBACK_CLR		0x1e8
 #define ANADIG_USB1_LOOPBACK_CLR		0x1e8
+#define ANADIG_USB1_LOOPBACK_UTMI_TESTSTART	BIT(0)
+
 #define ANADIG_USB2_LOOPBACK_SET		0x244
 #define ANADIG_USB2_LOOPBACK_SET		0x244
 #define ANADIG_USB2_LOOPBACK_CLR		0x248
 #define ANADIG_USB2_LOOPBACK_CLR		0x248
 
 
@@ -479,6 +494,144 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy,
 	return 0;
 	return 0;
 }
 }
 
 
+#define MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT	100
+static int mxs_charger_data_contact_detect(struct mxs_phy *x)
+{
+	struct regmap *regmap = x->regmap_anatop;
+	int i, stable_contact_count = 0;
+	u32 val;
+
+	/* Check if vbus is valid */
+	regmap_read(regmap, ANADIG_USB1_VBUS_DET_STAT, &val);
+	if (!(val & ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)) {
+		dev_err(x->phy.dev, "vbus is not valid\n");
+		return -EINVAL;
+	}
+
+	/* Enable charger detector */
+	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR,
+				ANADIG_USB1_CHRG_DETECT_EN_B);
+	/*
+	 * - Do not check whether a charger is connected to the USB port
+	 * - Check whether the USB plug has been in contact with each other
+	 */
+	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
+			ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
+			ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
+
+	/* Check if plug is connected */
+	for (i = 0; i < MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT; i++) {
+		regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
+		if (val & ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT) {
+			stable_contact_count++;
+			if (stable_contact_count > 5)
+				/* Data pin makes contact */
+				break;
+			else
+				usleep_range(5000, 10000);
+		} else {
+			stable_contact_count = 0;
+			usleep_range(5000, 6000);
+		}
+	}
+
+	if (i == MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT) {
+		dev_err(x->phy.dev,
+			"Data pin can't make good contact.\n");
+		/* Disable charger detector */
+		regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
+				ANADIG_USB1_CHRG_DETECT_EN_B |
+				ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static enum usb_charger_type mxs_charger_primary_detection(struct mxs_phy *x)
+{
+	struct regmap *regmap = x->regmap_anatop;
+	enum usb_charger_type chgr_type = UNKNOWN_TYPE;
+	u32 val;
+
+	/*
+	 * - Do check whether a charger is connected to the USB port
+	 * - Do not Check whether the USB plug has been in contact with
+	 *   each other
+	 */
+	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR,
+			ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
+			ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
+
+	msleep(100);
+
+	/* Check if it is a charger */
+	regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
+	if (!(val & ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED)) {
+		chgr_type = SDP_TYPE;
+		dev_dbg(x->phy.dev, "It is a stardard downstream port\n");
+	}
+
+	/* Disable charger detector */
+	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
+			ANADIG_USB1_CHRG_DETECT_EN_B |
+			ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
+
+	return chgr_type;
+}
+
+/*
+ * It must be called after DP is pulled up, which is used to
+ * differentiate DCP and CDP.
+ */
+enum usb_charger_type mxs_charger_secondary_detection(struct mxs_phy *x)
+{
+	struct regmap *regmap = x->regmap_anatop;
+	int val;
+
+	msleep(80);
+
+	regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
+	if (val & ANADIG_USB1_CHRG_DET_STAT_DM_STATE) {
+		dev_dbg(x->phy.dev, "It is a dedicate charging port\n");
+		return DCP_TYPE;
+	} else {
+		dev_dbg(x->phy.dev, "It is a charging downstream port\n");
+		return CDP_TYPE;
+	}
+}
+
+static enum usb_charger_type mxs_phy_charger_detect(struct usb_phy *phy)
+{
+	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
+	struct regmap *regmap = mxs_phy->regmap_anatop;
+	void __iomem *base = phy->io_priv;
+	enum usb_charger_type chgr_type = UNKNOWN_TYPE;
+
+	if (mxs_charger_data_contact_detect(mxs_phy))
+		return chgr_type;
+
+	chgr_type = mxs_charger_primary_detection(mxs_phy);
+
+	if (chgr_type != SDP_TYPE) {
+		/* Pull up DP via test */
+		writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
+				base + HW_USBPHY_DEBUG_CLR);
+		regmap_write(regmap, ANADIG_USB1_LOOPBACK_SET,
+				ANADIG_USB1_LOOPBACK_UTMI_TESTSTART);
+
+		chgr_type = mxs_charger_secondary_detection(mxs_phy);
+
+		/* Stop the test */
+		regmap_write(regmap, ANADIG_USB1_LOOPBACK_CLR,
+				ANADIG_USB1_LOOPBACK_UTMI_TESTSTART);
+		writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
+				base + HW_USBPHY_DEBUG_SET);
+	}
+
+	return chgr_type;
+}
+
 static int mxs_phy_probe(struct platform_device *pdev)
 static int mxs_phy_probe(struct platform_device *pdev)
 {
 {
 	struct resource *res;
 	struct resource *res;
@@ -567,6 +720,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
 	mxs_phy->phy.notify_disconnect	= mxs_phy_on_disconnect;
 	mxs_phy->phy.notify_disconnect	= mxs_phy_on_disconnect;
 	mxs_phy->phy.type		= USB_PHY_TYPE_USB2;
 	mxs_phy->phy.type		= USB_PHY_TYPE_USB2;
 	mxs_phy->phy.set_wakeup		= mxs_phy_set_wakeup;
 	mxs_phy->phy.set_wakeup		= mxs_phy_set_wakeup;
+	mxs_phy->phy.charger_detect	= mxs_phy_charger_detect;
 
 
 	mxs_phy->clk = clk;
 	mxs_phy->clk = clk;
 	mxs_phy->data = of_id->data;
 	mxs_phy->data = of_id->data;

+ 2 - 1
drivers/usb/phy/phy-tahvo.c

@@ -368,7 +368,8 @@ static int tahvo_usb_probe(struct platform_device *pdev)
 	tu->extcon = devm_extcon_dev_allocate(&pdev->dev, tahvo_cable);
 	tu->extcon = devm_extcon_dev_allocate(&pdev->dev, tahvo_cable);
 	if (IS_ERR(tu->extcon)) {
 	if (IS_ERR(tu->extcon)) {
 		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
 		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
-		return -ENOMEM;
+		ret = PTR_ERR(tu->extcon);
+		goto err_disable_clk;
 	}
 	}
 
 
 	ret = devm_extcon_dev_register(&pdev->dev, tu->extcon);
 	ret = devm_extcon_dev_register(&pdev->dev, tu->extcon);

+ 13 - 11
drivers/usb/renesas_usbhs/common.c

@@ -485,6 +485,10 @@ static const struct of_device_id usbhs_of_match[] = {
 		.compatible = "renesas,usbhs-r8a7796",
 		.compatible = "renesas,usbhs-r8a7796",
 		.data = (void *)USBHS_TYPE_RCAR_GEN3,
 		.data = (void *)USBHS_TYPE_RCAR_GEN3,
 	},
 	},
+	{
+		.compatible = "renesas,usbhs-r8a77995",
+		.data = (void *)USBHS_TYPE_RCAR_GEN3_WITH_PLL,
+	},
 	{
 	{
 		.compatible = "renesas,rcar-gen2-usbhs",
 		.compatible = "renesas,rcar-gen2-usbhs",
 		.data = (void *)USBHS_TYPE_RCAR_GEN2,
 		.data = (void *)USBHS_TYPE_RCAR_GEN2,
@@ -501,7 +505,6 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev)
 {
 {
 	struct renesas_usbhs_platform_info *info;
 	struct renesas_usbhs_platform_info *info;
 	struct renesas_usbhs_driver_param *dparam;
 	struct renesas_usbhs_driver_param *dparam;
-	const struct of_device_id *of_id = of_match_device(usbhs_of_match, dev);
 	u32 tmp;
 	u32 tmp;
 	int gpio;
 	int gpio;
 
 
@@ -510,7 +513,7 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev)
 		return NULL;
 		return NULL;
 
 
 	dparam = &info->driver_param;
 	dparam = &info->driver_param;
-	dparam->type = of_id ? (uintptr_t)of_id->data : 0;
+	dparam->type = (uintptr_t)of_device_get_match_data(dev);
 	if (!of_property_read_u32(dev->of_node, "renesas,buswait", &tmp))
 	if (!of_property_read_u32(dev->of_node, "renesas,buswait", &tmp))
 		dparam->buswait_bwait = tmp;
 		dparam->buswait_bwait = tmp;
 	gpio = of_get_named_gpio_flags(dev->of_node, "renesas,enable-gpio", 0,
 	gpio = of_get_named_gpio_flags(dev->of_node, "renesas,enable-gpio", 0,
@@ -519,8 +522,12 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev)
 		dparam->enable_gpio = gpio;
 		dparam->enable_gpio = gpio;
 
 
 	if (dparam->type == USBHS_TYPE_RCAR_GEN2 ||
 	if (dparam->type == USBHS_TYPE_RCAR_GEN2 ||
-	    dparam->type == USBHS_TYPE_RCAR_GEN3)
+	    dparam->type == USBHS_TYPE_RCAR_GEN3 ||
+	    dparam->type == USBHS_TYPE_RCAR_GEN3_WITH_PLL) {
 		dparam->has_usb_dmac = 1;
 		dparam->has_usb_dmac = 1;
+		dparam->pipe_configs = usbhsc_new_pipe;
+		dparam->pipe_size = ARRAY_SIZE(usbhsc_new_pipe);
+	}
 
 
 	return info;
 	return info;
 }
 }
@@ -577,17 +584,12 @@ static int usbhs_probe(struct platform_device *pdev)
 	switch (priv->dparam.type) {
 	switch (priv->dparam.type) {
 	case USBHS_TYPE_RCAR_GEN2:
 	case USBHS_TYPE_RCAR_GEN2:
 		priv->pfunc = usbhs_rcar2_ops;
 		priv->pfunc = usbhs_rcar2_ops;
-		if (!priv->dparam.pipe_configs) {
-			priv->dparam.pipe_configs = usbhsc_new_pipe;
-			priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_new_pipe);
-		}
 		break;
 		break;
 	case USBHS_TYPE_RCAR_GEN3:
 	case USBHS_TYPE_RCAR_GEN3:
 		priv->pfunc = usbhs_rcar3_ops;
 		priv->pfunc = usbhs_rcar3_ops;
-		if (!priv->dparam.pipe_configs) {
-			priv->dparam.pipe_configs = usbhsc_new_pipe;
-			priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_new_pipe);
-		}
+		break;
+	case USBHS_TYPE_RCAR_GEN3_WITH_PLL:
+		priv->pfunc = usbhs_rcar3_with_pll_ops;
 		break;
 		break;
 	default:
 	default:
 		if (!info->platform_callback.get_id) {
 		if (!info->platform_callback.get_id) {

+ 48 - 0
drivers/usb/renesas_usbhs/rcar3.c

@@ -15,24 +15,39 @@
 #include "rcar3.h"
 #include "rcar3.h"
 
 
 #define LPSTS		0x102
 #define LPSTS		0x102
+#define UGCTRL		0x180	/* 32-bit register */
 #define UGCTRL2		0x184	/* 32-bit register */
 #define UGCTRL2		0x184	/* 32-bit register */
+#define UGSTS		0x188	/* 32-bit register */
 
 
 /* Low Power Status register (LPSTS) */
 /* Low Power Status register (LPSTS) */
 #define LPSTS_SUSPM	0x4000
 #define LPSTS_SUSPM	0x4000
 
 
+/* R-Car D3 only: USB General control register (UGCTRL) */
+#define UGCTRL_PLLRESET		0x00000001
+#define UGCTRL_CONNECT		0x00000004
+
 /*
 /*
  * USB General control register 2 (UGCTRL2)
  * USB General control register 2 (UGCTRL2)
  * Remarks: bit[31:11] and bit[9:6] should be 0
  * Remarks: bit[31:11] and bit[9:6] should be 0
  */
  */
 #define UGCTRL2_RESERVED_3	0x00000001	/* bit[3:0] should be B'0001 */
 #define UGCTRL2_RESERVED_3	0x00000001	/* bit[3:0] should be B'0001 */
+#define UGCTRL2_USB0SEL_HSUSB	0x00000020
 #define UGCTRL2_USB0SEL_OTG	0x00000030
 #define UGCTRL2_USB0SEL_OTG	0x00000030
 #define UGCTRL2_VBUSSEL		0x00000400
 #define UGCTRL2_VBUSSEL		0x00000400
 
 
+/* R-Car D3 only: USB General status register (UGSTS) */
+#define UGSTS_LOCK		0x00000100
+
 static void usbhs_write32(struct usbhs_priv *priv, u32 reg, u32 data)
 static void usbhs_write32(struct usbhs_priv *priv, u32 reg, u32 data)
 {
 {
 	iowrite32(data, priv->base + reg);
 	iowrite32(data, priv->base + reg);
 }
 }
 
 
+static u32 usbhs_read32(struct usbhs_priv *priv, u32 reg)
+{
+	return ioread32(priv->base + reg);
+}
+
 static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
 static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
 				void __iomem *base, int enable)
 				void __iomem *base, int enable)
 {
 {
@@ -52,6 +67,34 @@ static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
 	return 0;
 	return 0;
 }
 }
 
 
+/* R-Car D3 needs to release UGCTRL.PLLRESET */
+static int usbhs_rcar3_power_and_pll_ctrl(struct platform_device *pdev,
+					  void __iomem *base, int enable)
+{
+	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+	u32 val;
+	int timeout = 1000;
+
+	if (enable) {
+		usbhs_write32(priv, UGCTRL, 0);	/* release PLLRESET */
+		usbhs_write32(priv, UGCTRL2, UGCTRL2_RESERVED_3 |
+			      UGCTRL2_USB0SEL_HSUSB);
+
+		usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
+		do {
+			val = usbhs_read32(priv, UGSTS);
+			udelay(1);
+		} while (!(val & UGSTS_LOCK) && timeout--);
+		usbhs_write32(priv, UGCTRL, UGCTRL_CONNECT);
+	} else {
+		usbhs_write32(priv, UGCTRL, 0);
+		usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
+		usbhs_write32(priv, UGCTRL, UGCTRL_PLLRESET);
+	}
+
+	return 0;
+}
+
 static int usbhs_rcar3_get_id(struct platform_device *pdev)
 static int usbhs_rcar3_get_id(struct platform_device *pdev)
 {
 {
 	return USBHS_GADGET;
 	return USBHS_GADGET;
@@ -61,3 +104,8 @@ const struct renesas_usbhs_platform_callback usbhs_rcar3_ops = {
 	.power_ctrl = usbhs_rcar3_power_ctrl,
 	.power_ctrl = usbhs_rcar3_power_ctrl,
 	.get_id = usbhs_rcar3_get_id,
 	.get_id = usbhs_rcar3_get_id,
 };
 };
+
+const struct renesas_usbhs_platform_callback usbhs_rcar3_with_pll_ops = {
+	.power_ctrl = usbhs_rcar3_power_and_pll_ctrl,
+	.get_id = usbhs_rcar3_get_id,
+};

+ 1 - 0
drivers/usb/renesas_usbhs/rcar3.h

@@ -1,3 +1,4 @@
 #include "common.h"
 #include "common.h"
 
 
 extern const struct renesas_usbhs_platform_callback usbhs_rcar3_ops;
 extern const struct renesas_usbhs_platform_callback usbhs_rcar3_ops;
+extern const struct renesas_usbhs_platform_callback usbhs_rcar3_with_pll_ops;

+ 5 - 0
include/linux/usb/gadget.h

@@ -188,6 +188,8 @@ struct usb_ep_caps {
  * @ops: Function pointers used to access hardware-specific operations.
  * @ops: Function pointers used to access hardware-specific operations.
  * @ep_list:the gadget's ep_list holds all of its endpoints
  * @ep_list:the gadget's ep_list holds all of its endpoints
  * @caps:The structure describing types and directions supported by endoint.
  * @caps:The structure describing types and directions supported by endoint.
+ * @enabled: The current endpoint enabled/disabled state.
+ * @claimed: True if this endpoint is claimed by a function.
  * @maxpacket:The maximum packet size used on this endpoint.  The initial
  * @maxpacket:The maximum packet size used on this endpoint.  The initial
  *	value can sometimes be reduced (hardware allowing), according to
  *	value can sometimes be reduced (hardware allowing), according to
  *	the endpoint descriptor used to configure the endpoint.
  *	the endpoint descriptor used to configure the endpoint.
@@ -349,6 +351,9 @@ struct usb_gadget_ops {
  *	or B-Peripheral wants to take host role.
  *	or B-Peripheral wants to take host role.
  * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
  * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
  *	MaxPacketSize.
  *	MaxPacketSize.
+ * @quirk_altset_not_supp: UDC controller doesn't support alt settings.
+ * @quirk_stall_not_supp: UDC controller doesn't support stalling.
+ * @quirk_zlp_not_supp: UDC controller doesn't support ZLP.
  * @quirk_avoids_skb_reserve: udc/platform wants to avoid skb_reserve() in
  * @quirk_avoids_skb_reserve: udc/platform wants to avoid skb_reserve() in
  *	u_ether.c to improve performance.
  *	u_ether.c to improve performance.
  * @is_selfpowered: if the gadget is self-powered.
  * @is_selfpowered: if the gadget is self-powered.

+ 3 - 2
include/linux/usb/renesas_usbhs.h

@@ -183,8 +183,9 @@ struct renesas_usbhs_driver_param {
 #define USBHS_USB_DMAC_XFER_SIZE	32	/* hardcode the xfer size */
 #define USBHS_USB_DMAC_XFER_SIZE	32	/* hardcode the xfer size */
 };
 };
 
 
-#define USBHS_TYPE_RCAR_GEN2	1
-#define USBHS_TYPE_RCAR_GEN3	2
+#define USBHS_TYPE_RCAR_GEN2		1
+#define USBHS_TYPE_RCAR_GEN3		2
+#define USBHS_TYPE_RCAR_GEN3_WITH_PLL	3
 
 
 /*
 /*
  * option:
  * option: