Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3515468a authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

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

Felipe writes:

USB: changes for v5.2 merge window

With a total of 50 non-merge commits, this is not a large pull
request. Most of the changes are, again, in dwc2 (37%) and dwc3 (32%)
with the rest of it scattered among other UDCs, function drivers and
device-tree bindings.

No really big feature this time around apart from support to Amlogic
being added to both dwc3 and dwc2 drivers.

* tag 'usb-for-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (50 commits)
  usb: dwc3: Rename DWC3_DCTL_LPM_ERRATA
  usb: dwc3: Fix default lpm_nyet_threshold value
  usb: dwc3: debug: Print GET_STATUS(device) tracepoint
  usb: dwc3: Do core validation early on probe
  usb: dwc3: gadget: Set lpm_capable
  usb: gadget: atmel: tie wake lock to running clock
  usb: gadget: atmel: support USB suspend
  usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled mask
  dwc2: gadget: Fix completed transfer size calculation in DDMA
  usb: dwc2: Set lpm mode parameters depend on HW configuration
  usb: dwc2: Fix channel disable flow
  usb: dwc2: Set actual frame number for completed ISOC transfer
  usb: gadget: do not use __constant_cpu_to_le16
  usb: dwc2: gadget: Increase descriptors count for ISOC's
  usb: introduce usb_ep_type_string() function
  usb: dwc3: move synchronize_irq() out of the spinlock protected block
  usb: dwc3: Free resource immediately after use
  usb: dwc3: of-simple: Convert to bulk clk API
  usb: dwc2: Delayed status support
  usb: gadget: udc: lpc32xx: rework interrupt handling
  ...
parents 12456e50 2e487d28
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
@@ -40,3 +40,91 @@ Example device nodes:
				phy-names = "usb2-phy", "usb3-phy";
			};
		};

Amlogic Meson G12A DWC3 USB SoC Controller Glue

The Amlogic G12A embeds a DWC3 USB IP Core configured for USB2 and USB3
in host-only mode, and a DWC2 IP Core configured for USB2 peripheral mode
only.

A glue connects the DWC3 core to USB2 PHYs and optionnaly to an USB3 PHY.

One of the USB2 PHY can be re-routed in peripheral mode to a DWC2 USB IP.

The DWC3 Glue controls the PHY routing and power, an interrupt line is
connected to the Glue to serve as OTG ID change detection.

Required properties:
- compatible:	Should be "amlogic,meson-g12a-usb-ctrl"
- clocks:	a handle for the "USB" clock
- resets:	a handle for the shared "USB" reset line
- reg:		The base address and length of the registers
- interrupts:	the interrupt specifier for the OTG detection
- phys: 	handle to used PHYs on the system
	- a <0> phandle can be used if a PHY is not used
- phy-names:	names of the used PHYs on the system :
	- "usb2-phy0" for USB2 PHY0 if USBHOST_A port is used
	- "usb2-phy1" for USB2 PHY1 if USBOTG_B port is used
	- "usb3-phy0" for USB3 PHY if USB3_0 is used
- dr_mode:	should be "host", "peripheral", or "otg" depending on
	the usage and configuration of the OTG Capable port.
	- "host" and "peripheral" means a fixed Host or Device only connection
	- "otg" means the port can be used as both Host or Device and
	  be switched automatically using the OTG ID pin.

Optional properties:
- vbus-supply:	should be a phandle to the regulator controlling the VBUS
		power supply when used in OTG switchable mode

Required child nodes:

A child node must exist to represent the core DWC3 IP block. The name of
the node is not important. The content of the node is defined in dwc3.txt.

A child node must exist to represent the core DWC2 IP block. The name of
the node is not important. The content of the node is defined in dwc2.txt.

PHY documentation is provided in the following places:
- Documentation/devicetree/bindings/phy/meson-g12a-usb2-phy.txt
- Documentation/devicetree/bindings/phy/meson-g12a-usb3-pcie-phy.txt

Example device nodes:
	usb: usb@ffe09000 {
			compatible = "amlogic,meson-g12a-usb-ctrl";
			reg = <0x0 0xffe09000 0x0 0xa0>;
			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
			#address-cells = <2>;
			#size-cells = <2>;
			ranges;

			clocks = <&clkc CLKID_USB>;
			resets = <&reset RESET_USB>;

			dr_mode = "otg";

			phys = <&usb2_phy0>, <&usb2_phy1>,
			       <&usb3_pcie_phy PHY_TYPE_USB3>;
			phy-names = "usb2-phy0", "usb2-phy1", "usb3-phy0";

			dwc2: usb@ff400000 {
				compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
				reg = <0x0 0xff400000 0x0 0x40000>;
				interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
				clock-names = "ddr";
				phys = <&usb2_phy1>;
				dr_mode = "peripheral";
				g-rx-fifo-size = <192>;
				g-np-tx-fifo-size = <128>;
				g-tx-fifo-size = <128 128 16 16 16>;
			};

			dwc3: usb@ff500000 {
				compatible = "snps,dwc3";
				reg = <0x0 0xff500000 0x0 0x100000>;
				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
				dr_mode = "host";
				snps,dis_u2_susphy_quirk;
				snps,quirk-frame-length-adjustment;
			};
	};
+7 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ Required properties:
  - "amlogic,meson8-usb": The DWC2 USB controller instance in Amlogic Meson8 SoCs;
  - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs;
  - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs;
  - "amlogic,meson-g12a-usb": The DWC2 USB controller instance in Amlogic G12A SoCs;
  - "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs;
  - snps,dwc2: A generic DWC2 USB controller with default parameters.
  - "st,stm32f4x9-fsotg": The DWC2 USB FS/HS controller instance in STM32F4x9 SoCs
@@ -31,12 +32,18 @@ Refer to clk/clock-bindings.txt for generic clock consumer properties
Optional properties:
- phys: phy provider specifier
- phy-names: shall be "usb2-phy"
- vbus-supply: reference to the VBUS regulator. Depending on the current mode
  this is enabled (in "host" mode") or disabled (in "peripheral" mode). The
  regulator is updated if the controller is configured in "otg" mode and the
  status changes between "host" and "peripheral".
Refer to phy/phy-bindings.txt for generic phy consumer properties
- dr_mode: shall be one of "host", "peripheral" and "otg"
  Refer to usb/generic.txt
- g-rx-fifo-size: size of rx fifo size in gadget mode.
- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
- snps,reset-phy-on-wake: If present indicates that we need to reset the PHY when
                          we detect a wakeup.  This is due to a hardware errata.

Deprecated properties:
- g-use-dma: gadget DMA mode is automatically detected
+7 −0
Original line number Diff line number Diff line
@@ -616,6 +616,7 @@
		dr_mode = "host";
		phys = <&usbphy2>;
		phy-names = "usb2-phy";
		snps,reset-phy-on-wake;
		status = "disabled";
	};

@@ -904,6 +905,8 @@
				clocks = <&cru SCLK_OTGPHY0>;
				clock-names = "phyclk";
				#clock-cells = <0>;
				resets = <&cru SRST_USBOTG_PHY>;
				reset-names = "phy-reset";
			};

			usbphy1: usb-phy@334 {
@@ -912,6 +915,8 @@
				clocks = <&cru SCLK_OTGPHY1>;
				clock-names = "phyclk";
				#clock-cells = <0>;
				resets = <&cru SRST_USBHOST0_PHY>;
				reset-names = "phy-reset";
			};

			usbphy2: usb-phy@348 {
@@ -920,6 +925,8 @@
				clocks = <&cru SCLK_OTGPHY2>;
				clock-names = "phyclk";
				#clock-cells = <0>;
				resets = <&cru SRST_USBHOST1_PHY>;
				reset-names = "phy-reset";
			};
		};
	};
+4 −3
Original line number Diff line number Diff line
@@ -3174,13 +3174,14 @@ static int usb_disable_remote_wakeup(struct usb_device *udev)
}

/* Count of wakeup-enabled devices at or below udev */
static unsigned wakeup_enabled_descendants(struct usb_device *udev)
unsigned usb_wakeup_enabled_descendants(struct usb_device *udev)
{
	struct usb_hub *hub = usb_hub_to_struct_hub(udev);

	return udev->do_remote_wakeup +
			(hub ? hub->wakeup_enabled_descendants : 0);
}
EXPORT_SYMBOL_GPL(usb_wakeup_enabled_descendants);

/*
 * usb_port_suspend - suspend a usb device's upstream port
@@ -3282,7 +3283,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
	 * Therefore we will turn on the suspend feature if udev or any of its
	 * descendants is enabled for remote wakeup.
	 */
	else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0)
	else if (PMSG_IS_AUTO(msg) || usb_wakeup_enabled_descendants(udev) > 0)
		status = set_port_feature(hub->hdev, port1,
				USB_PORT_FEAT_SUSPEND);
	else {
@@ -3686,7 +3687,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
		}
		if (udev)
			hub->wakeup_enabled_descendants +=
					wakeup_enabled_descendants(udev);
					usb_wakeup_enabled_descendants(udev);
	}

	if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
+199 −0
Original line number Diff line number Diff line
@@ -1020,6 +1020,205 @@ int dwc2_hsotg_wait_bit_clear(struct dwc2_hsotg *hsotg, u32 offset, u32 mask,
	return -ETIMEDOUT;
}

/*
 * Initializes the FSLSPClkSel field of the HCFG register depending on the
 * PHY type
 */
void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
{
	u32 hcfg, val;

	if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
	     hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
	     hsotg->params.ulpi_fs_ls) ||
	    hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
		/* Full speed PHY */
		val = HCFG_FSLSPCLKSEL_48_MHZ;
	} else {
		/* High speed PHY running at full speed or high speed */
		val = HCFG_FSLSPCLKSEL_30_60_MHZ;
	}

	dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val);
	hcfg = dwc2_readl(hsotg, HCFG);
	hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
	hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT;
	dwc2_writel(hsotg, hcfg, HCFG);
}

static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
{
	u32 usbcfg, ggpio, i2cctl;
	int retval = 0;

	/*
	 * core_init() is now called on every switch so only call the
	 * following for the first time through
	 */
	if (select_phy) {
		dev_dbg(hsotg->dev, "FS PHY selected\n");

		usbcfg = dwc2_readl(hsotg, GUSBCFG);
		if (!(usbcfg & GUSBCFG_PHYSEL)) {
			usbcfg |= GUSBCFG_PHYSEL;
			dwc2_writel(hsotg, usbcfg, GUSBCFG);

			/* Reset after a PHY select */
			retval = dwc2_core_reset(hsotg, false);

			if (retval) {
				dev_err(hsotg->dev,
					"%s: Reset failed, aborting", __func__);
				return retval;
			}
		}

		if (hsotg->params.activate_stm_fs_transceiver) {
			ggpio = dwc2_readl(hsotg, GGPIO);
			if (!(ggpio & GGPIO_STM32_OTG_GCCFG_PWRDWN)) {
				dev_dbg(hsotg->dev, "Activating transceiver\n");
				/*
				 * STM32F4x9 uses the GGPIO register as general
				 * core configuration register.
				 */
				ggpio |= GGPIO_STM32_OTG_GCCFG_PWRDWN;
				dwc2_writel(hsotg, ggpio, GGPIO);
			}
		}
	}

	/*
	 * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
	 * do this on HNP Dev/Host mode switches (done in dev_init and
	 * host_init).
	 */
	if (dwc2_is_host_mode(hsotg))
		dwc2_init_fs_ls_pclk_sel(hsotg);

	if (hsotg->params.i2c_enable) {
		dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");

		/* Program GUSBCFG.OtgUtmiFsSel to I2C */
		usbcfg = dwc2_readl(hsotg, GUSBCFG);
		usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL;
		dwc2_writel(hsotg, usbcfg, GUSBCFG);

		/* Program GI2CCTL.I2CEn */
		i2cctl = dwc2_readl(hsotg, GI2CCTL);
		i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK;
		i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT;
		i2cctl &= ~GI2CCTL_I2CEN;
		dwc2_writel(hsotg, i2cctl, GI2CCTL);
		i2cctl |= GI2CCTL_I2CEN;
		dwc2_writel(hsotg, i2cctl, GI2CCTL);
	}

	return retval;
}

static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
{
	u32 usbcfg, usbcfg_old;
	int retval = 0;

	if (!select_phy)
		return 0;

	usbcfg = dwc2_readl(hsotg, GUSBCFG);
	usbcfg_old = usbcfg;

	/*
	 * HS PHY parameters. These parameters are preserved during soft reset
	 * so only program the first time. Do a soft reset immediately after
	 * setting phyif.
	 */
	switch (hsotg->params.phy_type) {
	case DWC2_PHY_TYPE_PARAM_ULPI:
		/* ULPI interface */
		dev_dbg(hsotg->dev, "HS ULPI PHY selected\n");
		usbcfg |= GUSBCFG_ULPI_UTMI_SEL;
		usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
		if (hsotg->params.phy_ulpi_ddr)
			usbcfg |= GUSBCFG_DDRSEL;

		/* Set external VBUS indicator as needed. */
		if (hsotg->params.oc_disable)
			usbcfg |= (GUSBCFG_ULPI_INT_VBUS_IND |
				   GUSBCFG_INDICATORPASSTHROUGH);
		break;
	case DWC2_PHY_TYPE_PARAM_UTMI:
		/* UTMI+ interface */
		dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n");
		usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
		if (hsotg->params.phy_utmi_width == 16)
			usbcfg |= GUSBCFG_PHYIF16;

		/* Set turnaround time */
		if (dwc2_is_device_mode(hsotg)) {
			usbcfg &= ~GUSBCFG_USBTRDTIM_MASK;
			if (hsotg->params.phy_utmi_width == 16)
				usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT;
			else
				usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT;
		}
		break;
	default:
		dev_err(hsotg->dev, "FS PHY selected at HS!\n");
		break;
	}

	if (usbcfg != usbcfg_old) {
		dwc2_writel(hsotg, usbcfg, GUSBCFG);

		/* Reset after setting the PHY parameters */
		retval = dwc2_core_reset(hsotg, false);
		if (retval) {
			dev_err(hsotg->dev,
				"%s: Reset failed, aborting", __func__);
			return retval;
		}
	}

	return retval;
}

int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
{
	u32 usbcfg;
	int retval = 0;

	if ((hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
	     hsotg->params.speed == DWC2_SPEED_PARAM_LOW) &&
	    hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
		/* If FS/LS mode with FS/LS PHY */
		retval = dwc2_fs_phy_init(hsotg, select_phy);
		if (retval)
			return retval;
	} else {
		/* High speed PHY */
		retval = dwc2_hs_phy_init(hsotg, select_phy);
		if (retval)
			return retval;
	}

	if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
	    hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
	    hsotg->params.ulpi_fs_ls) {
		dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
		usbcfg = dwc2_readl(hsotg, GUSBCFG);
		usbcfg |= GUSBCFG_ULPI_FS_LS;
		usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M;
		dwc2_writel(hsotg, usbcfg, GUSBCFG);
	} else {
		usbcfg = dwc2_readl(hsotg, GUSBCFG);
		usbcfg &= ~GUSBCFG_ULPI_FS_LS;
		usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
		dwc2_writel(hsotg, usbcfg, GUSBCFG);
	}

	return retval;
}

MODULE_DESCRIPTION("DESIGNWARE HS OTG Core");
MODULE_AUTHOR("Synopsys, Inc.");
MODULE_LICENSE("Dual BSD/GPL");
Loading