Linux-USB Archive on lore.kernel.org
 help / color / Atom feed
* [Patch V2 00/18] Tegra XUSB OTG support
@ 2019-12-18  9:16 Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch Nagarjuna Kristam
                   ` (18 more replies)
  0 siblings, 19 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

This patch series adds OTG support on XUSB hardware used in Tegra210 and
Tegra186 SoCs.

This patchset is composed with :
 - dt bindings of XUSB Pad Controller
 - dt bindings for XUSB device Driver
 - Tegra PHY driver for usb-role-switch and usb-phy
 - Tegra XUSB host mode driver to support OTG mode
 - Tegra XUSB device mode driver to use usb-phy and multi device mode
 - dts for XUSB pad controller
 - dts for xudc

Tegra Pad controller driver register for role switch updates for
OTG/peripheral capable USB ports and adds usb-phy for that corresponding
USB ports.

Host and Device mode drivers gets usb-phy from USB2's phy and registers
notifier for role changes to perform corresponding role tasks.

Tests done:
 - device mode support using micro-B USB cable connection between ubuntu
   host and DUT on micro-B port
 - host mode support by connecting pen-drive to micro USB port on DUT
   using micro-B OTG cable.
 - toggling between these 2 modes by hot plugging corresponding cables.

DUT: Jetson-tx1, Jetson tx2.

V2:
 - Updated usb-role-switch documentation for Padctl driver.
 - Update XUDC bindings doc as suggested by Rob.
 - Used standard error codes for error return.
 - Added of_platform_depopulate during error and driver removal.
 - Updated error variable during phy initialization in XUDC driver.
 - Updated Tegra210 soc dtb file as per changes to binding doc.

Nagarjuna Kristam (18):
  dt-bindings: phy: tegra-xusb: Add usb-role-switch
  dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding
  phy: tegra: xusb: Add usb-role-switch support
  phy: tegra: xusb: Add usb-phy support
  phy: tegra: xusb: Add support to get companion USB 3 port
  phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210
  phy: tegra: xusb: Add set_mode support for utmi phy on Tegra186
  usb: xhci-tegra: Add OTG support
  usb: gadget: tegra-xudc: Remove usb-role-switch support
  usb: gadget: tegra-xudc: Add usb-phy support
  usb: gadget: tegra-xudc: use phy_set_mode to set/unset device mode
  usb: gadget: tegra-xudc: support multiple device modes
  arm64: tegra: update OTG port entries for jetson-tx1
  arm64: tegra: update OTG port entries for jetson-tx2
  arm64: tegra: Add xudc node for Tegra210
  arm64: tegra: Enable xudc on Jetson TX1
  arm64: tegra: Add xudc node for Tegra186
  arm64: tegra: Enable xudc node on Jetson TX2

 .../bindings/phy/nvidia,tegra124-xusb-padctl.txt   |   6 +
 .../devicetree/bindings/usb/nvidia,tegra-xudc.yaml | 190 ++++++++++++++
 arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts |  23 +-
 arch/arm64/boot/dts/nvidia/tegra186.dtsi           |  19 ++
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi     |  34 ++-
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  19 ++
 drivers/phy/tegra/Kconfig                          |   1 +
 drivers/phy/tegra/xusb-tegra186.c                  | 109 ++++++--
 drivers/phy/tegra/xusb-tegra210.c                  | 126 ++++++++--
 drivers/phy/tegra/xusb.c                           | 134 ++++++++++
 drivers/phy/tegra/xusb.h                           |   5 +
 drivers/usb/gadget/udc/tegra-xudc.c                | 276 ++++++++++++++-------
 drivers/usb/host/xhci-tegra.c                      | 225 ++++++++++++++++-
 include/linux/phy/tegra/xusb.h                     |   2 +
 14 files changed, 1031 insertions(+), 138 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml

-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-19 13:05   ` Thierry Reding
  2019-12-18  9:16 ` [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding Nagarjuna Kristam
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Add usb-role-switch property for Tegra210 and Tegra186 platforms. This
entry is used by XUSB pad controller driver to register for role changes
for OTG/Peripheral capable USB 2 ports.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - Moved usb-role-switch to seperate Required section as suggested by Thierry.
 - Added reference to usb/usb-conn-gpio.txt for connector subnode.
---
 .../devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt         | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
index 9fb682e..23bf354 100644
--- a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
+++ b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
@@ -174,6 +174,12 @@ Required properties:
   - "device": for USB device mode
   - "otg": for USB OTG mode
 
+Required properties for OTG/Peripheral capable USB2 ports:
+- usb-role-switch: Boolean property to indicate that the port support OTG or
+  peripheral mode. If present, the port supports switching between USB host
+  and peripheral roles. Connector should be added as subnode.
+  See usb/usb-conn-gpio.txt.
+
 Optional properties:
 - nvidia,internal: A boolean property whose presence determines that a port
   is internal. In the absence of this property the port is considered to be
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18 23:24   ` Rob Herring
  2019-12-19 13:10   ` Thierry Reding
  2019-12-18  9:16 ` [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support Nagarjuna Kristam
                   ` (16 subsequent siblings)
  18 siblings, 2 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Add device-tree binding documentation for the XUSB device mode controller
present on Tegra210 and Tegra186 SoC. This controller supports the USB 3.0
specification.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - used enum instead of oneOf and const.
 - Moved reg, reg-names, clocks, clock-names to property section from allOf.
 - Limited allOf to min and max items based on soc.
 - Updated description for power-domains.
 - Added V1 reference
---
V1
 - This document is yaml version of [1], with difference of usb-role-switch
   removal.
[1] https://patchwork.kernel.org/patch/11156253/ 
---
 .../devicetree/bindings/usb/nvidia,tegra-xudc.yaml | 190 +++++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml

diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml
new file mode 100644
index 0000000..b84ed8e
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/usb/nvidia,tegra-xudc.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Device tree binding for NVIDIA Tegra XUSB device mode controller (XUDC)
+
+description:
+  The Tegra XUDC controller supports both USB 2.0 HighSpeed/FullSpeed and
+  USB 3.0 SuperSpeed protocols.
+
+maintainers:
+  - Nagarjuna Kristam <nkristam@nvidia.com>
+  - JC Kuo <jckuo@nvidia.com>
+  - Thierry Reding <treding@nvidia.com>
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - nvidia,tegra210-xudc # For Tegra210
+          - nvidia,tegra186-xudc # For Tegra186
+
+  reg:
+    minItems: 2
+    maxItems: 3
+    items:
+      - description: XUSB device controller registers
+      - description: XUSB device PCI Config registers
+      - description: XUSB device registers.
+
+  reg-names:
+    minItems: 2
+    maxItems: 3
+    items:
+      - const: base
+      - const: fpci
+      - const: ipfs
+
+  interrupts:
+    maxItems: 1
+    description: Must contain the XUSB device interrupt.
+
+  clocks:
+    minItems: 4
+    maxItems: 5
+    items:
+      - description: Clock to enable core XUSB dev clock.
+      - description: Clock to enable XUSB super speed clock.
+      - description: Clock to enable XUSB super speed dev clock.
+      - description: Clock to enable XUSB high speed dev clock.
+      - description: Clock to enable XUSB full speed dev clock.
+
+  clock-names:
+    minItems: 4
+    maxItems: 5
+    items:
+     - const: dev
+     - const: ss
+     - const: ss_src
+     - const: fs_src
+     - const: hs_src
+
+  power-domains:
+    maxItems: 2
+    items:
+      - description: XUSBB(device) power-domain
+      - description: XUSBA(superspeed) power-domain
+
+  power-domain-names:
+    maxItems: 2
+    items:
+      - const: dev
+      - const: ss
+
+  nvidia,xusb-padctl:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description:
+      phandle to the XUSB pad controller that is used to configure the USB pads
+      used by the XUDC controller.
+
+  phys:
+    minItems: 1
+    description:
+      Must contain an entry for each entry in phy-names.
+      See ../phy/phy-bindings.txt for details.
+
+  phy-names:
+    minItems: 1
+    items:
+      - const: usb2-0
+      - const: usb2-1
+      - const: usb2-2
+      - const: usb2-3
+      - const: usb3-0
+      - const: usb3-1
+      - const: usb3-2
+      - const: usb3-3
+
+  avddio-usb-supply:
+    description: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
+
+  hvdd-usb-supply:
+    description: USB controller power supply. Must supply 3.3 V.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - clocks
+  - clock-names
+  - power-domains
+  - power-domain-names
+  - nvidia,xusb-padctl
+  - phys
+  - phy-names
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - nvidia,tegra210-xudc
+    then:
+      properties:
+        reg:
+          minItems: 3
+        reg-names:
+          minItems: 3
+        clocks:
+          minItems: 5
+        clock-names:
+          minItems: 5
+      required:
+        - avddio-usb-supply
+        - hvdd-usb-supply
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - nvidia,tegra186-xudc
+    then:
+      properties:
+        reg:
+          maxItems: 2
+        reg-names:
+          maxItems: 2
+        clocks:
+          maxItems: 4
+        clock-names:
+          maxItems: 4
+
+examples:
+  - |
+    #include <dt-bindings/clock/tegra210-car.h>
+    #include <dt-bindings/gpio/tegra-gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    usb@700d0000 {
+        compatible = "nvidia,tegra210-xudc";
+        reg = <0x0 0x700d0000 0x0 0x8000>,
+              <0x0 0x700d8000 0x0 0x1000>,
+              <0x0 0x700d9000 0x0 0x1000>;
+        reg-names = "base", "fpci", "ipfs";
+
+        interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+
+        clocks = <&tegra_car TEGRA210_CLK_XUSB_DEV>,
+                 <&tegra_car TEGRA210_CLK_XUSB_SS>,
+                 <&tegra_car TEGRA210_CLK_XUSB_SSP_SRC>,
+                 <&tegra_car TEGRA210_CLK_XUSB_FS_SRC>,
+                 <&tegra_car TEGRA210_CLK_XUSB_HS_SRC>;
+        clock-names = "dev", "ss", "ss_src", "fs_src", "hs_src";
+
+        power-domains = <&pd_xusbdev>, <&pd_xusbss>;
+        power-domain-names = "dev", "ss";
+
+        nvidia,xusb-padctl = <&padctl>;
+
+        phys = <&micro_b>;
+        phy-names = "usb2-0";
+
+        avddio-usb-supply = <&vdd_pex_1v05>;
+        hvdd-usb-supply = <&vdd_3v3_sys>;
+    };
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-19 13:26   ` Thierry Reding
  2019-12-26  6:42   ` JC Kuo
  2019-12-18  9:16 ` [Patch V2 04/18] phy: tegra: xusb: Add usb-phy support Nagarjuna Kristam
                   ` (15 subsequent siblings)
  18 siblings, 2 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

If usb-role-switch property is present in USB 2 port, register
usb-role-switch to receive usb role changes.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - Removed dev_set_drvdata for port->dev.
 - Added of_platform_depopulate during error handling and driver removal.
---
 drivers/phy/tegra/Kconfig |  1 +
 drivers/phy/tegra/xusb.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
 drivers/phy/tegra/xusb.h  |  3 +++
 3 files changed, 46 insertions(+)

diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig
index f9817c3..df07c4d 100644
--- a/drivers/phy/tegra/Kconfig
+++ b/drivers/phy/tegra/Kconfig
@@ -2,6 +2,7 @@
 config PHY_TEGRA_XUSB
 	tristate "NVIDIA Tegra XUSB pad controller driver"
 	depends on ARCH_TEGRA
+	select USB_CONN_GPIO
 	help
 	  Choose this option if you have an NVIDIA Tegra SoC.
 
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index f98ec39..dc00b42 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -523,6 +523,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
 	port->dev.type = &tegra_xusb_port_type;
 	port->dev.of_node = of_node_get(np);
 	port->dev.parent = padctl->dev;
+	port->dev.driver = padctl->dev->driver;
 
 	err = dev_set_name(&port->dev, "%s-%u", name, index);
 	if (err < 0)
@@ -541,6 +542,10 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
 
 static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
 {
+	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
+		of_platform_depopulate(&port->dev);
+		usb_role_switch_unregister(port->usb_role_sw);
+	}
 	device_unregister(&port->dev);
 }
 
@@ -551,11 +556,42 @@ static const char *const modes[] = {
 	[USB_DR_MODE_OTG] = "otg",
 };
 
+static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
+{
+	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
+
+	return 0;
+}
+
+static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
+{
+	int err = 0;
+	struct usb_role_switch_desc role_sx_desc = {
+					.set = tegra_xusb_role_sw_set,
+					.fwnode = dev_fwnode(&port->dev),
+						   };
+
+	port->usb_role_sw = usb_role_switch_register(&port->dev,
+						&role_sx_desc);
+	if (IS_ERR(port->usb_role_sw)) {
+		err = PTR_ERR(port->usb_role_sw);
+		if (err != EPROBE_DEFER)
+			dev_err(&port->dev, "Failed to register USB role SW: %d",
+				err);
+	}
+
+	/* populate connector entry */
+	of_platform_populate(port->dev.of_node, NULL, NULL, &port->dev);
+
+	return err;
+}
+
 static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
 {
 	struct tegra_xusb_port *port = &usb2->base;
 	struct device_node *np = port->dev.of_node;
 	const char *mode;
+	int err;
 
 	usb2->internal = of_property_read_bool(np, "nvidia,internal");
 
@@ -572,6 +608,12 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
 		usb2->mode = USB_DR_MODE_HOST;
 	}
 
+	if (of_property_read_bool(np, "usb-role-switch")) {
+		err = tegra_xusb_setup_usb_role_switch(port);
+		if (err < 0)
+			return err;
+	}
+
 	usb2->supply = devm_regulator_get(&port->dev, "vbus");
 	return PTR_ERR_OR_ZERO(usb2->supply);
 }
diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
index da94fcc..9f27899 100644
--- a/drivers/phy/tegra/xusb.h
+++ b/drivers/phy/tegra/xusb.h
@@ -12,6 +12,7 @@
 #include <linux/workqueue.h>
 
 #include <linux/usb/otg.h>
+#include <linux/usb/role.h>
 
 /* legacy entry points for backwards-compatibility */
 int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev);
@@ -266,6 +267,8 @@ struct tegra_xusb_port {
 	struct list_head list;
 	struct device dev;
 
+	struct usb_role_switch *usb_role_sw;
+
 	const struct tegra_xusb_port_ops *ops;
 };
 
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 04/18] phy: tegra: xusb: Add usb-phy support
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (2 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-19 13:37   ` Thierry Reding
  2019-12-18  9:16 ` [Patch V2 05/18] phy: tegra: xusb: Add support to get companion USB 3 port Nagarjuna Kristam
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

For USB 2 ports that has usb-role-switch enabled, add usb-phy for
corresponding USB 2 phy. USB role changes from role switch are then
updated to corresponding host and device mode drivers via usb-phy notifier
block.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - Added dev_set_drvdata for port->dev.
---
 drivers/phy/tegra/xusb.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/phy/tegra/xusb.h |  2 ++
 2 files changed, 73 insertions(+)

diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index dc00b42..5bde8f1 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -533,6 +533,8 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
 	if (err < 0)
 		goto unregister;
 
+	dev_set_drvdata(&port->dev, port);
+
 	return 0;
 
 unregister:
@@ -545,6 +547,8 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
 	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
 		of_platform_depopulate(&port->dev);
 		usb_role_switch_unregister(port->usb_role_sw);
+		cancel_work_sync(&port->usb_phy_work);
+		usb_remove_phy(&port->usb_phy);
 	}
 	device_unregister(&port->dev);
 }
@@ -556,16 +560,59 @@ static const char *const modes[] = {
 	[USB_DR_MODE_OTG] = "otg",
 };
 
+static void tegra_xusb_usb_phy_work(struct work_struct *work)
+{
+	struct tegra_xusb_port *port = container_of(work,
+				struct tegra_xusb_port, usb_phy_work);
+	enum usb_role role = usb_role_switch_get_role(port->usb_role_sw);
+
+	dev_dbg(&port->dev, "%s calling notifier for role %d\n", __func__,
+		role);
+
+	atomic_notifier_call_chain(&port->usb_phy.notifier, role,
+				   &port->usb_phy);
+}
+
 static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
 {
+	struct tegra_xusb_port *port = dev_get_drvdata(dev);
+
 	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
 
+	schedule_work(&port->usb_phy_work);
+
+	return 0;
+}
+
+static int tegra_xusb_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	struct tegra_xusb_port *port = container_of(otg->usb_phy,
+					struct tegra_xusb_port, usb_phy);
+
+	if (gadget != NULL)
+		schedule_work(&port->usb_phy_work);
+
+	return 0;
+}
+
+static int tegra_xusb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct tegra_xusb_port *port = container_of(otg->usb_phy,
+					struct tegra_xusb_port, usb_phy);
+
+	if (host != NULL)
+		schedule_work(&port->usb_phy_work);
+
 	return 0;
 }
 
+
 static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
 {
 	int err = 0;
+	struct tegra_xusb_lane *lane = tegra_xusb_find_lane(port->padctl,
+							"usb2", port->index);
 	struct usb_role_switch_desc role_sx_desc = {
 					.set = tegra_xusb_role_sw_set,
 					.fwnode = dev_fwnode(&port->dev),
@@ -578,6 +625,30 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
 		if (err != EPROBE_DEFER)
 			dev_err(&port->dev, "Failed to register USB role SW: %d",
 				err);
+		return err;
+	}
+
+	INIT_WORK(&port->usb_phy_work, tegra_xusb_usb_phy_work);
+
+	port->usb_phy.otg = devm_kzalloc(&port->dev,
+					 sizeof(struct usb_otg), GFP_KERNEL);
+	if (!port->usb_phy.otg)
+		return -ENOMEM;
+
+	/*
+	 * Assign phy dev to usb-phy dev. Host/device drivers can use phy
+	 * reference to retrieve usb-phy details.
+	 */
+	port->usb_phy.dev = &lane->pad->lanes[port->index]->dev;
+	port->usb_phy.dev->driver = port->padctl->dev->driver;
+	port->usb_phy.otg->usb_phy = &port->usb_phy;
+	port->usb_phy.otg->set_peripheral = tegra_xusb_set_peripheral;
+	port->usb_phy.otg->set_host = tegra_xusb_set_host;
+
+	err = usb_add_phy_dev(&port->usb_phy);
+	if (err < 0) {
+		dev_err(&port->dev, "Failed to add usbphy: %d\n", err);
+		return err;
 	}
 
 	/* populate connector entry */
diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
index 9f27899..2345657 100644
--- a/drivers/phy/tegra/xusb.h
+++ b/drivers/phy/tegra/xusb.h
@@ -268,6 +268,8 @@ struct tegra_xusb_port {
 	struct device dev;
 
 	struct usb_role_switch *usb_role_sw;
+	struct work_struct usb_phy_work;
+	struct usb_phy usb_phy;
 
 	const struct tegra_xusb_port_ops *ops;
 };
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 05/18] phy: tegra: xusb: Add support to get companion USB 3 port
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (3 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 04/18] phy: tegra: xusb: Add usb-phy support Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-26  7:03   ` JC Kuo
  2019-12-18  9:16 ` [Patch V2 06/18] phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210 Nagarjuna Kristam
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Tegra XUSB host, device mode driver requires the USB 3 companion port
number for corresponding USB 2 port. Add API to retrieve the same.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - Added -ENODEV as return instead of -1, to sync other errors.
---
 drivers/phy/tegra/xusb.c       | 21 +++++++++++++++++++++
 include/linux/phy/tegra/xusb.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 5bde8f1..e75cd71 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -1256,6 +1256,27 @@ int tegra_phy_xusb_utmi_port_reset(struct phy *phy)
 }
 EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_port_reset);
 
+int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
+				    unsigned int port)
+{
+	struct tegra_xusb_usb2_port *usb2 = tegra_xusb_find_usb2_port(padctl,
+								      port);
+	struct tegra_xusb_usb3_port *usb3;
+	int i;
+
+	if (!usb2)
+		return -EINVAL;
+
+	for (i = 0; i < padctl->soc->ports.usb3.count; i++) {
+		usb3 = tegra_xusb_find_usb3_port(padctl, i);
+		if (usb3 && usb3->port == usb2->base.index)
+			return usb3->base.index;
+	}
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_usb3_companion);
+
 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 MODULE_DESCRIPTION("Tegra XUSB Pad Controller driver");
 MODULE_LICENSE("GPL v2");
diff --git a/include/linux/phy/tegra/xusb.h b/include/linux/phy/tegra/xusb.h
index 1235865..71d9569 100644
--- a/include/linux/phy/tegra/xusb.h
+++ b/include/linux/phy/tegra/xusb.h
@@ -21,4 +21,6 @@ int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl,
 int tegra_xusb_padctl_set_vbus_override(struct tegra_xusb_padctl *padctl,
 					bool val);
 int tegra_phy_xusb_utmi_port_reset(struct phy *phy);
+int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
+					 unsigned int port);
 #endif /* PHY_TEGRA_XUSB_H */
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 06/18] phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (4 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 05/18] phy: tegra: xusb: Add support to get companion USB 3 port Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 07/18] phy: tegra: xusb: Add set_mode support for utmi phy on Tegra186 Nagarjuna Kristam
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Add support for set_mode on USB 2 phy. This allow XUSB host/device mode
drivers to configure the hardware to corresponding modes.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 drivers/phy/tegra/xusb-tegra210.c | 126 ++++++++++++++++++++++++++++++--------
 1 file changed, 99 insertions(+), 27 deletions(-)

diff --git a/drivers/phy/tegra/xusb-tegra210.c b/drivers/phy/tegra/xusb-tegra210.c
index 394913b..6610b1d7 100644
--- a/drivers/phy/tegra/xusb-tegra210.c
+++ b/drivers/phy/tegra/xusb-tegra210.c
@@ -236,6 +236,7 @@
 #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18
 #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf
 #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8
+#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0
 
 struct tegra210_xusb_fuse_calibration {
 	u32 hs_curr_level[4];
@@ -935,6 +936,98 @@ static int tegra210_usb2_phy_exit(struct phy *phy)
 	return tegra210_xusb_padctl_disable(lane->pad->padctl);
 }
 
+static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
+					      bool status)
+{
+	u32 value;
+
+	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
+
+	if (status) {
+		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
+		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
+			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
+		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
+			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
+	} else {
+		value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
+	}
+
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
+
+	return 0;
+}
+
+static int tegra210_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
+					    bool status)
+{
+	u32 value;
+
+	dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear");
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
+
+	if (status) {
+		if (value & XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON) {
+			value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
+			padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
+			usleep_range(1000, 2000);
+
+			value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
+		}
+
+		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
+			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
+		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED <<
+			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
+	} else {
+		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
+			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
+		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
+			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
+	}
+
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
+
+	return 0;
+}
+
+static int tegra210_usb2_phy_set_mode(struct phy *phy, enum phy_mode mode,
+				      int submode)
+{
+	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
+	struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl,
+								lane->index);
+	int err = 0;
+
+	mutex_lock(&padctl->lock);
+
+	dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode);
+
+	if (mode == PHY_MODE_USB_OTG) {
+		if (submode == USB_ROLE_HOST) {
+			tegra210_xusb_padctl_id_override(padctl, true);
+
+			err = regulator_enable(port->supply);
+		} else if (submode == USB_ROLE_DEVICE) {
+			tegra210_xusb_padctl_vbus_override(padctl, true);
+		} else if (submode == USB_ROLE_NONE) {
+			if (regulator_is_enabled(port->supply))
+				regulator_disable(port->supply);
+
+			tegra210_xusb_padctl_id_override(padctl, false);
+			tegra210_xusb_padctl_vbus_override(padctl, false);
+		}
+	}
+
+	mutex_unlock(&padctl->lock);
+
+	return err;
+}
+
 static int tegra210_usb2_phy_power_on(struct phy *phy)
 {
 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
@@ -1048,9 +1141,11 @@ static int tegra210_usb2_phy_power_on(struct phy *phy)
 	padctl_writel(padctl, value,
 		      XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));
 
-	err = regulator_enable(port->supply);
-	if (err)
-		return err;
+	if (port->supply && port->mode == USB_DR_MODE_HOST) {
+		err = regulator_enable(port->supply);
+		if (err)
+			return err;
+	}
 
 	mutex_lock(&padctl->lock);
 
@@ -1164,6 +1259,7 @@ static const struct phy_ops tegra210_usb2_phy_ops = {
 	.exit = tegra210_usb2_phy_exit,
 	.power_on = tegra210_usb2_phy_power_on,
 	.power_off = tegra210_usb2_phy_power_off,
+	.set_mode = tegra210_usb2_phy_set_mode,
 	.owner = THIS_MODULE,
 };
 
@@ -2023,30 +2119,6 @@ static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
 	.map = tegra210_usb3_port_map,
 };
 
-static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
-					      bool status)
-{
-	u32 value;
-
-	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");
-
-	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
-
-	if (status) {
-		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
-		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
-			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
-		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
-			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
-	} else {
-		value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
-	}
-
-	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
-
-	return 0;
-}
-
 static int tegra210_utmi_port_reset(struct phy *phy)
 {
 	struct tegra_xusb_padctl *padctl;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 07/18] phy: tegra: xusb: Add set_mode support for utmi phy on Tegra186
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (5 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 06/18] phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210 Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 08/18] usb: xhci-tegra: Add OTG support Nagarjuna Kristam
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Add support for set_mode on utmi phy. This allow XUSB host/device mode
drivers to configure the hardware to corresponding modes.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 drivers/phy/tegra/xusb-tegra186.c | 109 ++++++++++++++++++++++++++++++--------
 1 file changed, 87 insertions(+), 22 deletions(-)

diff --git a/drivers/phy/tegra/xusb-tegra186.c b/drivers/phy/tegra/xusb-tegra186.c
index 84c2739..9a45160 100644
--- a/drivers/phy/tegra/xusb-tegra186.c
+++ b/drivers/phy/tegra/xusb-tegra186.c
@@ -301,6 +301,92 @@ static void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy)
 	tegra186_utmi_bias_pad_power_off(padctl);
 }
 
+static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
+					       bool status)
+{
+	u32 value;
+
+	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");
+
+	value = padctl_readl(padctl, USB2_VBUS_ID);
+
+	if (status) {
+		value |= VBUS_OVERRIDE;
+		value &= ~ID_OVERRIDE(~0);
+		value |= ID_OVERRIDE_FLOATING;
+	} else {
+		value &= ~VBUS_OVERRIDE;
+	}
+
+	padctl_writel(padctl, value, USB2_VBUS_ID);
+
+	return 0;
+}
+
+static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
+					    bool status)
+{
+	u32 value;
+
+	dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear");
+
+	value = padctl_readl(padctl, USB2_VBUS_ID);
+
+	if (status) {
+		if (value & VBUS_OVERRIDE) {
+			value &= ~VBUS_OVERRIDE;
+			padctl_writel(padctl, value, USB2_VBUS_ID);
+			usleep_range(1000, 2000);
+
+			value = padctl_readl(padctl, USB2_VBUS_ID);
+		}
+
+		value &= ~ID_OVERRIDE(~0);
+		value |= ID_OVERRIDE_GROUNDED;
+	} else {
+		value &= ~ID_OVERRIDE(~0);
+		value |= ID_OVERRIDE_FLOATING;
+	}
+
+	padctl_writel(padctl, value, USB2_VBUS_ID);
+
+	return 0;
+}
+
+static int tegra186_utmi_phy_set_mode(struct phy *phy, enum phy_mode mode,
+				      int submode)
+{
+	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
+	struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl,
+								lane->index);
+	int err = 0;
+
+	mutex_lock(&padctl->lock);
+
+	dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode);
+
+	if (mode == PHY_MODE_USB_OTG) {
+		if (submode == USB_ROLE_HOST) {
+			tegra186_xusb_padctl_id_override(padctl, true);
+
+			err = regulator_enable(port->supply);
+		} else if (submode == USB_ROLE_DEVICE) {
+			tegra186_xusb_padctl_vbus_override(padctl, true);
+		} else if (submode == USB_ROLE_NONE) {
+			if (regulator_is_enabled(port->supply))
+				regulator_disable(port->supply);
+
+			tegra186_xusb_padctl_id_override(padctl, false);
+			tegra186_xusb_padctl_vbus_override(padctl, false);
+		}
+	}
+
+	mutex_unlock(&padctl->lock);
+
+	return err;
+}
+
 static int tegra186_utmi_phy_power_on(struct phy *phy)
 {
 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
@@ -439,6 +525,7 @@ static const struct phy_ops utmi_phy_ops = {
 	.exit = tegra186_utmi_phy_exit,
 	.power_on = tegra186_utmi_phy_power_on,
 	.power_off = tegra186_utmi_phy_power_off,
+	.set_mode = tegra186_utmi_phy_set_mode,
 	.owner = THIS_MODULE,
 };
 
@@ -857,28 +944,6 @@ static void tegra186_xusb_padctl_remove(struct tegra_xusb_padctl *padctl)
 {
 }
 
-static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
-					       bool status)
-{
-	u32 value;
-
-	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");
-
-	value = padctl_readl(padctl, USB2_VBUS_ID);
-
-	if (status) {
-		value |= VBUS_OVERRIDE;
-		value &= ~ID_OVERRIDE(~0);
-		value |= ID_OVERRIDE_FLOATING;
-	} else {
-		value &= ~VBUS_OVERRIDE;
-	}
-
-	padctl_writel(padctl, value, USB2_VBUS_ID);
-
-	return 0;
-}
-
 static const struct tegra_xusb_padctl_ops tegra186_xusb_padctl_ops = {
 	.probe = tegra186_xusb_padctl_probe,
 	.remove = tegra186_xusb_padctl_remove,
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 08/18] usb: xhci-tegra: Add OTG support
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (6 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 07/18] phy: tegra: xusb: Add set_mode support for utmi phy on Tegra186 Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 09/18] usb: gadget: tegra-xudc: Remove usb-role-switch support Nagarjuna Kristam
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Get usb-phy's for availbale USB 2 phys. Register id notifiers for available
usb-phy's to receive role change notifications. Perform PP for the received
role change usb ports.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - Removed extra line before tegra_xusb_probe API.
---
 drivers/usb/host/xhci-tegra.c | 225 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 224 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 0b58ef3..22f1d36 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -24,6 +24,9 @@
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/role.h>
 #include <soc/tegra/pmc.h>
 
 #include "xhci.h"
@@ -203,6 +206,7 @@ struct tegra_xusb_soc {
 
 	bool scale_ss_clock;
 	bool has_ipfs;
+	bool otg_reset_sspi;
 };
 
 struct tegra_xusb_context {
@@ -250,6 +254,14 @@ struct tegra_xusb {
 	struct phy **phys;
 	unsigned int num_phys;
 
+	struct usb_phy **usbphy;
+	unsigned int num_usb_phys;
+	int otg_usb2_port;
+	int otg_usb3_port;
+	bool host_mode;
+	struct notifier_block id_nb;
+	struct work_struct id_work;
+
 	/* Firmware loading related */
 	struct {
 		size_t size;
@@ -1081,6 +1093,205 @@ static int tegra_xusb_enable_firmware_messages(struct tegra_xusb *tegra)
 	return err;
 }
 
+static void tegra_xhci_set_port_power(struct tegra_xusb *tegra, bool main,
+						 bool set)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+	struct usb_hcd *hcd = main ?  xhci->main_hcd : xhci->shared_hcd;
+	int wait = (!main && !set) ? 1000 : 10;
+	u16 typeReq = set ? SetPortFeature : ClearPortFeature;
+	u16 wIndex = main ? tegra->otg_usb2_port + 1 : tegra->otg_usb3_port + 1;
+	u32 status;
+	u32 stat_power = main ? USB_PORT_STAT_POWER : USB_SS_PORT_STAT_POWER;
+	u32 status_val = set ? stat_power : 0;
+
+	dev_dbg(tegra->dev, "%s:%s %s PP\n", __func__, set ? "set" : "clear",
+							main ? "HS" : "SS");
+
+	tegra_xhci_hc_driver.hub_control(hcd, typeReq, USB_PORT_FEAT_POWER,
+					 wIndex, NULL, 0);
+
+	do {
+		tegra_xhci_hc_driver.hub_control(hcd, GetPortStatus, 0, wIndex,
+					(char *) &status, sizeof(status));
+		if (status_val == (status & stat_power))
+			break;
+
+		if (!main && !set)
+			usleep_range(600, 700);
+		else
+			usleep_range(10, 20);
+	} while (--wait > 0);
+
+	if (status_val != (status & stat_power))
+		dev_info(tegra->dev, "failed to %s %s PP %d\n",
+						set ? "set" : "clear",
+						main ? "HS" : "SS", status);
+}
+
+static struct phy *tegra_xusb_get_phy(struct tegra_xusb *tegra, char *name,
+								int port)
+{
+	int i, phy_count = 0;
+
+	for (i = 0; i < tegra->soc->num_types; i++) {
+		if (!strncmp(tegra->soc->phy_types[i].name, "usb2",
+							    strlen(name)))
+			return tegra->phys[phy_count+port];
+
+		phy_count += tegra->soc->phy_types[i].num;
+	}
+
+	return NULL;
+}
+
+static void tegra_xhci_id_work(struct work_struct *work)
+{
+	struct tegra_xusb *tegra = container_of(work, struct tegra_xusb,
+						id_work);
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+	struct tegra_xusb_mbox_msg msg;
+	struct phy *phy = tegra_xusb_get_phy(tegra, "usb2",
+						    tegra->otg_usb2_port);
+	u32 status;
+	int ret;
+
+	dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off");
+
+	mutex_lock(&tegra->lock);
+
+	if (tegra->host_mode)
+		phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_HOST);
+	else
+		phy_set_mode_ext(phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+
+	mutex_unlock(&tegra->lock);
+
+	if (tegra->host_mode) {
+		/* switch to host mode */
+		if (tegra->otg_usb3_port >= 0) {
+			if (tegra->soc->otg_reset_sspi) {
+				/* set PP=0 */
+				tegra_xhci_hc_driver.hub_control(
+					xhci->shared_hcd, GetPortStatus,
+					0, tegra->otg_usb3_port+1,
+					(char *) &status, sizeof(status));
+				if (status & USB_SS_PORT_STAT_POWER)
+					tegra_xhci_set_port_power(tegra, false,
+								  false);
+
+				/* reset OTG port SSPI */
+				msg.cmd = MBOX_CMD_RESET_SSPI;
+				msg.data = tegra->otg_usb3_port+1;
+
+				ret = tegra_xusb_mbox_send(tegra, &msg);
+				if (ret < 0) {
+					dev_info(tegra->dev,
+						"failed to RESET_SSPI %d\n",
+						ret);
+				}
+			}
+
+			tegra_xhci_set_port_power(tegra, false, true);
+		}
+
+		tegra_xhci_set_port_power(tegra, true, true);
+
+	} else {
+		if (tegra->otg_usb3_port >= 0)
+			tegra_xhci_set_port_power(tegra, false, false);
+
+		tegra_xhci_set_port_power(tegra, true, false);
+	}
+}
+
+static int tegra_xusb_get_usb2_port(struct tegra_xusb *tegra,
+					      struct usb_phy *usbphy)
+{
+	int i;
+
+	for (i = 0; i < tegra->num_usb_phys; i++) {
+		if (tegra->usbphy[i] && usbphy == tegra->usbphy[i])
+			return i;
+	}
+
+	return -1;
+}
+
+static int tegra_xhci_id_notify(struct notifier_block *nb,
+					 unsigned long action, void *data)
+{
+	struct tegra_xusb *tegra = container_of(nb, struct tegra_xusb,
+						    id_nb);
+	struct usb_phy *usbphy = (struct usb_phy *)data;
+
+	dev_dbg(tegra->dev, "%s: action is %ld", __func__, action);
+
+	if ((tegra->host_mode && action == USB_ROLE_HOST) ||
+		(!tegra->host_mode && action != USB_ROLE_HOST)) {
+		dev_dbg(tegra->dev, "Same role(%d) received. Ignore",
+							tegra->host_mode);
+		return NOTIFY_OK;
+	}
+
+	tegra->otg_usb2_port = tegra_xusb_get_usb2_port(tegra, usbphy);
+	tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(
+							tegra->padctl,
+							tegra->otg_usb2_port);
+
+	tegra->host_mode = (action == USB_ROLE_HOST) ? true : false;
+
+	schedule_work(&tegra->id_work);
+
+	return NOTIFY_OK;
+}
+
+static int tegra_xusb_init_usb_phy(struct tegra_xusb *tegra)
+{
+	int i;
+
+	tegra->usbphy = devm_kcalloc(tegra->dev, tegra->num_usb_phys,
+				   sizeof(*tegra->usbphy), GFP_KERNEL);
+	if (!tegra->usbphy)
+		return -ENOMEM;
+
+	INIT_WORK(&tegra->id_work, tegra_xhci_id_work);
+	tegra->id_nb.notifier_call = tegra_xhci_id_notify;
+
+	for (i = 0; i < tegra->num_usb_phys; i++) {
+		struct phy *phy = tegra_xusb_get_phy(tegra, "usb2", i);
+
+		if (!phy)
+			continue;
+
+		tegra->usbphy[i] = devm_usb_get_phy_by_node(tegra->dev,
+							phy->dev.of_node,
+							&tegra->id_nb);
+		if (!IS_ERR(tegra->usbphy[i])) {
+			dev_dbg(tegra->dev, "usbphy-%d registered", i);
+			otg_set_host(tegra->usbphy[i]->otg, &tegra->hcd->self);
+		} else {
+			/*
+			 * usb-phy is optional, continue if its not available.
+			 */
+			tegra->usbphy[i] = NULL;
+		}
+	}
+
+	return 0;
+}
+
+static void tegra_xusb_deinit_usb_phy(struct tegra_xusb *tegra)
+{
+	int i;
+
+	cancel_work_sync(&tegra->id_work);
+
+	for (i = 0; i < tegra->num_usb_phys; i++)
+		if (tegra->usbphy[i])
+			otg_set_host(tegra->usbphy[i]->otg, NULL);
+}
+
 static int tegra_xusb_probe(struct platform_device *pdev)
 {
 	struct tegra_xusb *tegra;
@@ -1254,8 +1465,11 @@ static int tegra_xusb_probe(struct platform_device *pdev)
 		goto put_powerdomains;
 	}
 
-	for (i = 0; i < tegra->soc->num_types; i++)
+	for (i = 0; i < tegra->soc->num_types; i++) {
+		if (!strncmp(tegra->soc->phy_types[i].name, "usb2", 4))
+			tegra->num_usb_phys = tegra->soc->phy_types[i].num;
 		tegra->num_phys += tegra->soc->phy_types[i].num;
+	}
 
 	tegra->phys = devm_kcalloc(&pdev->dev, tegra->num_phys,
 				   sizeof(*tegra->phys), GFP_KERNEL);
@@ -1384,6 +1598,12 @@ static int tegra_xusb_probe(struct platform_device *pdev)
 		goto remove_usb3;
 	}
 
+	err = tegra_xusb_init_usb_phy(tegra);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to Init usb-phy: %d\n", err);
+		goto remove_usb3;
+	}
+
 	return 0;
 
 remove_usb3:
@@ -1420,6 +1640,8 @@ static int tegra_xusb_remove(struct platform_device *pdev)
 	struct tegra_xusb *tegra = platform_get_drvdata(pdev);
 	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
 
+	tegra_xusb_deinit_usb_phy(tegra);
+
 	usb_remove_hcd(xhci->shared_hcd);
 	usb_put_hcd(xhci->shared_hcd);
 	xhci->shared_hcd = NULL;
@@ -1733,6 +1955,7 @@ static const struct tegra_xusb_soc tegra210_soc = {
 	},
 	.scale_ss_clock = false,
 	.has_ipfs = true,
+	.otg_reset_sspi = true,
 	.mbox = {
 		.cmd = 0xe4,
 		.data_in = 0xe8,
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 09/18] usb: gadget: tegra-xudc: Remove usb-role-switch support
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (7 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 08/18] usb: xhci-tegra: Add OTG support Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 10/18] usb: gadget: tegra-xudc: Add usb-phy support Nagarjuna Kristam
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Padctl driver will act as a central driver to receive USB role changes via
usb-role-switch. This is updated to corresponding host, device drivers.
Hence remove usb-role-switch from XUDC driver.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 drivers/usb/gadget/udc/tegra-xudc.c | 65 ++++++++++---------------------------
 1 file changed, 17 insertions(+), 48 deletions(-)

diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 634c2c1..6ddb974 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -477,8 +477,8 @@ struct tegra_xudc {
 
 	struct clk_bulk_data *clks;
 
-	enum usb_role device_mode;
-	struct usb_role_switch *usb_role_sw;
+	enum usb_role role;
+	bool device_mode;
 	struct work_struct usb_role_sw_work;
 
 	struct phy *usb3_phy;
@@ -596,6 +596,8 @@ static void tegra_xudc_device_mode_on(struct tegra_xudc *xudc)
 {
 	int err;
 
+	if (xudc->device_mode)
+		return;
 	pm_runtime_get_sync(xudc->dev);
 
 	err = phy_power_on(xudc->utmi_phy);
@@ -610,7 +612,8 @@ static void tegra_xudc_device_mode_on(struct tegra_xudc *xudc)
 
 	tegra_xusb_padctl_set_vbus_override(xudc->padctl, true);
 
-	xudc->device_mode = USB_ROLE_DEVICE;
+	xudc->device_mode = true;
+
 }
 
 static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc)
@@ -619,6 +622,9 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc)
 	u32 pls, val;
 	int err;
 
+	if (!xudc->device_mode)
+		return;
+
 	dev_dbg(xudc->dev, "device mode off\n");
 
 	connected = !!(xudc_readl(xudc, PORTSC) & PORTSC_CCS);
@@ -643,7 +649,7 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc)
 		xudc_writel(xudc, val, PORTSC);
 	}
 
-	xudc->device_mode = USB_ROLE_NONE;
+	xudc->device_mode = false;
 
 	/* Wait for disconnect event. */
 	if (connected)
@@ -668,31 +674,13 @@ static void tegra_xudc_usb_role_sw_work(struct work_struct *work)
 	struct tegra_xudc *xudc = container_of(work, struct tegra_xudc,
 					       usb_role_sw_work);
 
-	if (!xudc->usb_role_sw ||
-		usb_role_switch_get_role(xudc->usb_role_sw) == USB_ROLE_DEVICE)
+	if (xudc->role == USB_ROLE_DEVICE)
 		tegra_xudc_device_mode_on(xudc);
 	else
 		tegra_xudc_device_mode_off(xudc);
 
 }
 
-static int tegra_xudc_usb_role_sw_set(struct device *dev, enum usb_role role)
-{
-	struct tegra_xudc *xudc = dev_get_drvdata(dev);
-	unsigned long flags;
-
-	dev_dbg(dev, "%s role is %d\n", __func__, role);
-
-	spin_lock_irqsave(&xudc->lock, flags);
-
-	if (!xudc->suspended)
-		schedule_work(&xudc->usb_role_sw_work);
-
-	spin_unlock_irqrestore(&xudc->lock, flags);
-
-	return 0;
-}
-
 static void tegra_xudc_plc_reset_work(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
@@ -729,8 +717,7 @@ static void tegra_xudc_port_reset_war_work(struct work_struct *work)
 
 	spin_lock_irqsave(&xudc->lock, flags);
 
-	if ((xudc->device_mode == USB_ROLE_DEVICE)
-			      && xudc->wait_for_sec_prc) {
+	if (xudc->device_mode && xudc->wait_for_sec_prc) {
 		pls = (xudc_readl(xudc, PORTSC) & PORTSC_PLS_MASK) >>
 			PORTSC_PLS_SHIFT;
 		dev_dbg(xudc->dev, "pls = %x\n", pls);
@@ -3457,7 +3444,6 @@ static int tegra_xudc_probe(struct platform_device *pdev)
 {
 	struct tegra_xudc *xudc;
 	struct resource *res;
-	struct usb_role_switch_desc role_sx_desc = { 0 };
 	unsigned int i;
 	int err;
 
@@ -3587,23 +3573,10 @@ static int tegra_xudc_probe(struct platform_device *pdev)
 	INIT_DELAYED_WORK(&xudc->port_reset_war_work,
 				tegra_xudc_port_reset_war_work);
 
-	if (of_property_read_bool(xudc->dev->of_node, "usb-role-switch")) {
-		role_sx_desc.set = tegra_xudc_usb_role_sw_set;
-		role_sx_desc.fwnode = dev_fwnode(xudc->dev);
-
-		xudc->usb_role_sw = usb_role_switch_register(xudc->dev,
-							&role_sx_desc);
-		if (IS_ERR(xudc->usb_role_sw)) {
-			err = PTR_ERR(xudc->usb_role_sw);
-			dev_err(xudc->dev, "Failed to register USB role SW: %d",
-					   err);
-			goto free_eps;
-		}
-	} else {
-		/* Set the mode as device mode and this keeps phy always ON */
-		dev_info(xudc->dev, "Set usb role to device mode always");
-		schedule_work(&xudc->usb_role_sw_work);
-	}
+	/* Set the mode as device mode and this keeps phy always ON */
+	dev_info(xudc->dev, "Set usb role to device mode always");
+	xudc->role = USB_ROLE_DEVICE;
+	schedule_work(&xudc->usb_role_sw_work);
 
 	pm_runtime_enable(&pdev->dev);
 
@@ -3643,11 +3616,7 @@ static int tegra_xudc_remove(struct platform_device *pdev)
 	pm_runtime_get_sync(xudc->dev);
 
 	cancel_delayed_work(&xudc->plc_reset_work);
-
-	if (xudc->usb_role_sw) {
-		usb_role_switch_unregister(xudc->usb_role_sw);
-		cancel_work_sync(&xudc->usb_role_sw_work);
-	}
+	cancel_work_sync(&xudc->usb_role_sw_work);
 
 	usb_del_gadget_udc(&xudc->gadget);
 
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 10/18] usb: gadget: tegra-xudc: Add usb-phy support
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (8 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 09/18] usb: gadget: tegra-xudc: Remove usb-role-switch support Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 11/18] usb: gadget: tegra-xudc: use phy_set_mode to set/unset device mode Nagarjuna Kristam
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

usb-phy is used to get notified on the USB role changes. Get usb-phy from
the utmi phy.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 drivers/usb/gadget/udc/tegra-xudc.c | 39 +++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 6ddb974..0f27d57 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -26,7 +26,9 @@
 #include <linux/reset.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 #include <linux/usb/role.h>
+#include <linux/usb/phy.h>
 #include <linux/workqueue.h>
 
 /* XUSB_DEV registers */
@@ -488,6 +490,9 @@ struct tegra_xudc {
 	bool suspended;
 	bool powergated;
 
+	struct usb_phy *usbphy;
+	struct notifier_block vbus_nb;
+
 	struct completion disconnect_complete;
 
 	bool selfpowered;
@@ -678,7 +683,22 @@ static void tegra_xudc_usb_role_sw_work(struct work_struct *work)
 		tegra_xudc_device_mode_on(xudc);
 	else
 		tegra_xudc_device_mode_off(xudc);
+}
+
+static int tegra_xudc_vbus_notifier(struct notifier_block *nb,
+					 unsigned long action, void *data)
+{
+	struct tegra_xudc *xudc = container_of(nb, struct tegra_xudc,
+					       vbus_nb);
+
+	dev_dbg(xudc->dev, "%s action is %ld\n", __func__, action);
+
+	xudc->role = (enum usb_role)action;
 
+	if (!xudc->suspended)
+		schedule_work(&xudc->usb_role_sw_work);
+
+	return NOTIFY_OK;
 }
 
 static void tegra_xudc_plc_reset_work(struct work_struct *work)
@@ -1949,6 +1969,9 @@ static int tegra_xudc_gadget_start(struct usb_gadget *gadget,
 		xudc_writel(xudc, val, CTRL);
 	}
 
+	if (xudc->usbphy)
+		otg_set_peripheral(xudc->usbphy->otg, gadget);
+
 	xudc->driver = driver;
 unlock:
 	dev_dbg(xudc->dev, "%s: ret value is %d", __func__, ret);
@@ -1969,6 +1992,9 @@ static int tegra_xudc_gadget_stop(struct usb_gadget *gadget)
 
 	spin_lock_irqsave(&xudc->lock, flags);
 
+	if (xudc->usbphy)
+		otg_set_peripheral(xudc->usbphy->otg, NULL);
+
 	val = xudc_readl(xudc, CTRL);
 	val &= ~(CTRL_IE | CTRL_ENABLE);
 	xudc_writel(xudc, val, CTRL);
@@ -3573,10 +3599,15 @@ static int tegra_xudc_probe(struct platform_device *pdev)
 	INIT_DELAYED_WORK(&xudc->port_reset_war_work,
 				tegra_xudc_port_reset_war_work);
 
-	/* Set the mode as device mode and this keeps phy always ON */
-	dev_info(xudc->dev, "Set usb role to device mode always");
-	xudc->role = USB_ROLE_DEVICE;
-	schedule_work(&xudc->usb_role_sw_work);
+	xudc->vbus_nb.notifier_call = tegra_xudc_vbus_notifier;
+	xudc->usbphy = devm_usb_get_phy_by_node(xudc->dev,
+						xudc->utmi_phy->dev.of_node,
+						&xudc->vbus_nb);
+	if (IS_ERR(xudc->usbphy)) {
+		err = PTR_ERR(xudc->usbphy);
+		dev_err(xudc->dev, "failed to get usbphy phy: %d\n", err);
+		goto free_eps;
+	}
 
 	pm_runtime_enable(&pdev->dev);
 
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 11/18] usb: gadget: tegra-xudc: use phy_set_mode to set/unset device mode
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (9 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 10/18] usb: gadget: tegra-xudc: Add usb-phy support Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 12/18] usb: gadget: tegra-xudc: support multiple device modes Nagarjuna Kristam
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

When device mode is set/uset, vbus override activity is done via
exported functions from padctl driver. Use phy_set_mode instead.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 drivers/usb/gadget/udc/tegra-xudc.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 0f27d57..283c320 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -615,7 +615,7 @@ static void tegra_xudc_device_mode_on(struct tegra_xudc *xudc)
 
 	dev_dbg(xudc->dev, "device mode on\n");
 
-	tegra_xusb_padctl_set_vbus_override(xudc->padctl, true);
+	phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG, USB_ROLE_DEVICE);
 
 	xudc->device_mode = true;
 
@@ -636,7 +636,7 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc)
 
 	reinit_completion(&xudc->disconnect_complete);
 
-	tegra_xusb_padctl_set_vbus_override(xudc->padctl, false);
+	phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
 
 	pls = (xudc_readl(xudc, PORTSC) & PORTSC_PLS_MASK) >>
 		PORTSC_PLS_SHIFT;
@@ -716,9 +716,11 @@ static void tegra_xudc_plc_reset_work(struct work_struct *work)
 
 		if (pls == PORTSC_PLS_INACTIVE) {
 			dev_info(xudc->dev, "PLS = Inactive. Toggle VBUS\n");
-			tegra_xusb_padctl_set_vbus_override(xudc->padctl,
-							      false);
-			tegra_xusb_padctl_set_vbus_override(xudc->padctl, true);
+			phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG,
+					 USB_ROLE_NONE);
+			phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG,
+					 USB_ROLE_DEVICE);
+
 			xudc->wait_csc = false;
 		}
 	}
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 12/18] usb: gadget: tegra-xudc: support multiple device modes
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (10 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 11/18] usb: gadget: tegra-xudc: use phy_set_mode to set/unset device mode Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 13/18] arm64: tegra: update OTG port entries for jetson-tx1 Nagarjuna Kristam
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

This change supports limited multiple device modes by:
- At most 4 ports contains OTG/Device capability.
- One port run as device mode at a time.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - Updated err variable on failure to get usbphy.
 - Corrected identation after tegra_xudc_phy_get API call in tegra_xudc_probe.
---
 drivers/usb/gadget/udc/tegra-xudc.c | 228 ++++++++++++++++++++++++++----------
 1 file changed, 167 insertions(+), 61 deletions(-)

diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 283c320..bf80fae 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -483,14 +483,15 @@ struct tegra_xudc {
 	bool device_mode;
 	struct work_struct usb_role_sw_work;
 
-	struct phy *usb3_phy;
-	struct phy *utmi_phy;
+	struct phy **usb3_phy;
+	struct phy **utmi_phy;
 
 	struct tegra_xudc_save_regs saved_regs;
 	bool suspended;
 	bool powergated;
 
-	struct usb_phy *usbphy;
+	struct usb_phy **usbphy;
+	int current_phy_index;
 	struct notifier_block vbus_nb;
 
 	struct completion disconnect_complete;
@@ -522,6 +523,7 @@ struct tegra_xudc_soc {
 	unsigned int num_supplies;
 	const char * const *clock_names;
 	unsigned int num_clks;
+	unsigned int num_phys;
 	bool u1_enable;
 	bool u2_enable;
 	bool lpm_enable;
@@ -605,17 +607,18 @@ static void tegra_xudc_device_mode_on(struct tegra_xudc *xudc)
 		return;
 	pm_runtime_get_sync(xudc->dev);
 
-	err = phy_power_on(xudc->utmi_phy);
+	err = phy_power_on(xudc->utmi_phy[xudc->current_phy_index]);
 	if (err < 0)
 		dev_err(xudc->dev, "utmi power on failed %d\n", err);
 
-	err = phy_power_on(xudc->usb3_phy);
+	err = phy_power_on(xudc->usb3_phy[xudc->current_phy_index]);
 	if (err < 0)
 		dev_err(xudc->dev, "usb3 phy power on failed %d\n", err);
 
 	dev_dbg(xudc->dev, "device mode on\n");
 
-	phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG, USB_ROLE_DEVICE);
+	phy_set_mode_ext(xudc->utmi_phy[xudc->current_phy_index],
+			 PHY_MODE_USB_OTG, USB_ROLE_DEVICE);
 
 	xudc->device_mode = true;
 
@@ -636,7 +639,8 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc)
 
 	reinit_completion(&xudc->disconnect_complete);
 
-	phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG, USB_ROLE_NONE);
+	phy_set_mode_ext(xudc->utmi_phy[xudc->current_phy_index],
+			 PHY_MODE_USB_OTG, USB_ROLE_NONE);
 
 	pls = (xudc_readl(xudc, PORTSC) & PORTSC_PLS_MASK) >>
 		PORTSC_PLS_SHIFT;
@@ -663,11 +667,11 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc)
 	/* Make sure interrupt handler has completed before powergating. */
 	synchronize_irq(xudc->irq);
 
-	err = phy_power_off(xudc->utmi_phy);
+	err = phy_power_off(xudc->utmi_phy[xudc->current_phy_index]);
 	if (err < 0)
 		dev_err(xudc->dev, "utmi_phy power off failed %d\n", err);
 
-	err = phy_power_off(xudc->usb3_phy);
+	err = phy_power_off(xudc->usb3_phy[xudc->current_phy_index]);
 	if (err < 0)
 		dev_err(xudc->dev, "usb3_phy power off failed %d\n", err);
 
@@ -685,17 +689,43 @@ static void tegra_xudc_usb_role_sw_work(struct work_struct *work)
 		tegra_xudc_device_mode_off(xudc);
 }
 
-static int tegra_xudc_vbus_notifier(struct notifier_block *nb,
+static int tegra_xudc_get_phy_index(struct tegra_xudc *xudc,
+					      struct usb_phy *usbphy)
+{
+	int i;
+
+	for (i = 0; i < xudc->soc->num_phys; i++) {
+		if (xudc->usbphy[i] && usbphy == xudc->usbphy[i])
+			return i;
+	}
+
+	dev_info(xudc->dev, "phy index could not be found for shared usb-phy");
+	return -1;
+}
+
+static int tegra_xudc_vbus_notify(struct notifier_block *nb,
 					 unsigned long action, void *data)
 {
 	struct tegra_xudc *xudc = container_of(nb, struct tegra_xudc,
 					       vbus_nb);
+	struct usb_phy *usbphy = (struct usb_phy *)data;
 
 	dev_dbg(xudc->dev, "%s action is %ld\n", __func__, action);
 
+	if ((xudc->device_mode && action == USB_ROLE_DEVICE) ||
+	    (!xudc->device_mode && action != USB_ROLE_DEVICE)) {
+		dev_info(xudc->dev, "Same role(%d) received. Ignore",
+			 xudc->device_mode);
+		return NOTIFY_OK;
+	}
+
 	xudc->role = (enum usb_role)action;
 
-	if (!xudc->suspended)
+	xudc->current_phy_index = tegra_xudc_get_phy_index(xudc, usbphy);
+	dev_dbg(xudc->dev, "%s current phy index is %d\n", __func__,
+		xudc->current_phy_index);
+
+	if (!xudc->suspended && xudc->current_phy_index != -1)
 		schedule_work(&xudc->usb_role_sw_work);
 
 	return NOTIFY_OK;
@@ -716,10 +746,12 @@ static void tegra_xudc_plc_reset_work(struct work_struct *work)
 
 		if (pls == PORTSC_PLS_INACTIVE) {
 			dev_info(xudc->dev, "PLS = Inactive. Toggle VBUS\n");
-			phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG,
-					 USB_ROLE_NONE);
-			phy_set_mode_ext(xudc->utmi_phy, PHY_MODE_USB_OTG,
-					 USB_ROLE_DEVICE);
+			phy_set_mode_ext(
+					xudc->utmi_phy[xudc->current_phy_index],
+					PHY_MODE_USB_OTG, USB_ROLE_NONE);
+			phy_set_mode_ext(
+					xudc->utmi_phy[xudc->current_phy_index],
+					PHY_MODE_USB_OTG, USB_ROLE_DEVICE);
 
 			xudc->wait_csc = false;
 		}
@@ -747,7 +779,8 @@ static void tegra_xudc_port_reset_war_work(struct work_struct *work)
 		if (pls == PORTSC_PLS_DISABLED) {
 			dev_dbg(xudc->dev, "toggle vbus\n");
 			/* PRC doesn't complete in 100ms, toggle the vbus */
-			ret = tegra_phy_xusb_utmi_port_reset(xudc->utmi_phy);
+			ret = tegra_phy_xusb_utmi_port_reset(
+				xudc->utmi_phy[xudc->current_phy_index]);
 			if (ret == 1)
 				xudc->wait_for_sec_prc = 0;
 		}
@@ -1935,7 +1968,7 @@ static int tegra_xudc_gadget_start(struct usb_gadget *gadget,
 	struct tegra_xudc *xudc = to_xudc(gadget);
 	unsigned long flags;
 	u32 val;
-	int ret;
+	int ret, i;
 
 	if (!driver)
 		return -EINVAL;
@@ -1971,8 +2004,9 @@ static int tegra_xudc_gadget_start(struct usb_gadget *gadget,
 		xudc_writel(xudc, val, CTRL);
 	}
 
-	if (xudc->usbphy)
-		otg_set_peripheral(xudc->usbphy->otg, gadget);
+	for (i = 0; i < xudc->soc->num_phys; i++)
+		if (xudc->usbphy[i])
+			otg_set_peripheral(xudc->usbphy[i]->otg, gadget);
 
 	xudc->driver = driver;
 unlock:
@@ -1989,13 +2023,15 @@ static int tegra_xudc_gadget_stop(struct usb_gadget *gadget)
 	struct tegra_xudc *xudc = to_xudc(gadget);
 	unsigned long flags;
 	u32 val;
+	int i;
 
 	pm_runtime_get_sync(xudc->dev);
 
 	spin_lock_irqsave(&xudc->lock, flags);
 
-	if (xudc->usbphy)
-		otg_set_peripheral(xudc->usbphy->otg, NULL);
+	for (i = 0; i < xudc->soc->num_phys; i++)
+		if (xudc->usbphy[i])
+			otg_set_peripheral(xudc->usbphy[i]->otg, NULL);
 
 	val = xudc_readl(xudc, CTRL);
 	val &= ~(CTRL_IE | CTRL_ENABLE);
@@ -3329,33 +3365,118 @@ static void tegra_xudc_device_params_init(struct tegra_xudc *xudc)
 	xudc_writel(xudc, val, CFG_DEV_SSPI_XFER);
 }
 
-static int tegra_xudc_phy_init(struct tegra_xudc *xudc)
+static int tegra_xudc_phy_get(struct tegra_xudc *xudc)
 {
-	int err;
+	int err = 0, i, usb3;
 
-	err = phy_init(xudc->utmi_phy);
-	if (err < 0) {
-		dev_err(xudc->dev, "utmi phy init failed: %d\n", err);
-		return err;
-	}
+	xudc->utmi_phy = devm_kcalloc(xudc->dev, xudc->soc->num_phys,
+					   sizeof(*xudc->utmi_phy), GFP_KERNEL);
+	if (!xudc->utmi_phy)
+		return -ENOMEM;
 
-	err = phy_init(xudc->usb3_phy);
-	if (err < 0) {
-		dev_err(xudc->dev, "usb3 phy init failed: %d\n", err);
-		goto exit_utmi_phy;
+	xudc->usb3_phy = devm_kcalloc(xudc->dev, xudc->soc->num_phys,
+					   sizeof(*xudc->usb3_phy), GFP_KERNEL);
+	if (!xudc->usb3_phy)
+		return -ENOMEM;
+
+	xudc->usbphy = devm_kcalloc(xudc->dev, xudc->soc->num_phys,
+					   sizeof(*xudc->usbphy), GFP_KERNEL);
+	if (!xudc->usbphy)
+		return -ENOMEM;
+
+	xudc->vbus_nb.notifier_call = tegra_xudc_vbus_notify;
+
+	for (i = 0; i < xudc->soc->num_phys; i++) {
+		char phy_name[] = "usb.-.";
+
+		/* Get USB2 phy */
+		snprintf(phy_name, sizeof(phy_name), "usb2-%d", i);
+		xudc->utmi_phy[i] = devm_phy_optional_get(xudc->dev, phy_name);
+		if (IS_ERR(xudc->utmi_phy[i])) {
+			err = PTR_ERR(xudc->utmi_phy[i]);
+			if (err != -EPROBE_DEFER)
+				dev_err(xudc->dev, "failed to get usb2-%d phy: %d\n",
+					i, err);
+
+			goto clean_up;
+		} else if (xudc->utmi_phy[i]) {
+			/* Get usb-phy, if utmi phy is available */
+			xudc->usbphy[i] = devm_usb_get_phy_by_node(xudc->dev,
+						xudc->utmi_phy[i]->dev.of_node,
+						&xudc->vbus_nb);
+			if (IS_ERR(xudc->usbphy[i])) {
+				err = PTR_ERR(xudc->usbphy[i]);
+				dev_err(xudc->dev, "failed to get usbphy-%d: %d\n",
+					i, err);
+				goto clean_up;
+			}
+		} else if (!xudc->utmi_phy[i]) {
+			/* if utmi phy is not available, ignore USB3 phy get */
+			continue;
+		}
+
+		/* Get USB3 phy */
+		usb3 = tegra_xusb_padctl_get_usb3_companion(xudc->padctl, i);
+		if (usb3 < 0)
+			continue;
+
+		snprintf(phy_name, sizeof(phy_name), "usb3-%d", usb3);
+		xudc->usb3_phy[i] = devm_phy_optional_get(xudc->dev, phy_name);
+		if (IS_ERR(xudc->usb3_phy[i])) {
+			err = PTR_ERR(xudc->usb3_phy[i]);
+			if (err != -EPROBE_DEFER)
+				dev_err(xudc->dev, "failed to get usb3-%d phy: %d\n",
+					usb3, err);
+
+			goto clean_up;
+		} else if (xudc->usb3_phy[i])
+			dev_dbg(xudc->dev, "usb3_phy-%d registered", usb3);
 	}
 
-	return 0;
+	return err;
+
+clean_up:
+	for (i = 0; i < xudc->soc->num_phys; i++) {
+		xudc->usb3_phy[i] = NULL;
+		xudc->utmi_phy[i] = NULL;
+		xudc->usbphy[i] = NULL;
+	}
 
-exit_utmi_phy:
-	phy_exit(xudc->utmi_phy);
 	return err;
 }
 
 static void tegra_xudc_phy_exit(struct tegra_xudc *xudc)
 {
-	phy_exit(xudc->usb3_phy);
-	phy_exit(xudc->utmi_phy);
+	int i;
+
+	for (i = 0; i < xudc->soc->num_phys; i++) {
+		phy_exit(xudc->usb3_phy[i]);
+		phy_exit(xudc->utmi_phy[i]);
+	}
+}
+
+static int tegra_xudc_phy_init(struct tegra_xudc *xudc)
+{
+	int err, i;
+
+	for (i = 0; i < xudc->soc->num_phys; i++) {
+		err = phy_init(xudc->utmi_phy[i]);
+		if (err < 0) {
+			dev_err(xudc->dev, "utmi phy init failed: %d\n", err);
+			goto exit_phy;
+		}
+
+		err = phy_init(xudc->usb3_phy[i]);
+		if (err < 0) {
+			dev_err(xudc->dev, "usb3 phy init failed: %d\n", err);
+			goto exit_phy;
+		}
+	}
+	return 0;
+
+exit_phy:
+	tegra_xudc_phy_exit(xudc);
+	return err;
 }
 
 static const char * const tegra210_xudc_supply_names[] = {
@@ -3383,6 +3504,7 @@ static struct tegra_xudc_soc tegra210_xudc_soc_data = {
 	.num_supplies = ARRAY_SIZE(tegra210_xudc_supply_names),
 	.clock_names = tegra210_xudc_clock_names,
 	.num_clks = ARRAY_SIZE(tegra210_xudc_clock_names),
+	.num_phys = 4,
 	.u1_enable = false,
 	.u2_enable = true,
 	.lpm_enable = false,
@@ -3395,6 +3517,7 @@ static struct tegra_xudc_soc tegra210_xudc_soc_data = {
 static struct tegra_xudc_soc tegra186_xudc_soc_data = {
 	.clock_names = tegra186_xudc_clock_names,
 	.num_clks = ARRAY_SIZE(tegra186_xudc_clock_names),
+	.num_phys = 4,
 	.u1_enable = true,
 	.u2_enable = true,
 	.lpm_enable = false,
@@ -3560,19 +3683,9 @@ static int tegra_xudc_probe(struct platform_device *pdev)
 		goto put_padctl;
 	}
 
-	xudc->usb3_phy = devm_phy_optional_get(&pdev->dev, "usb3");
-	if (IS_ERR(xudc->usb3_phy)) {
-		err = PTR_ERR(xudc->usb3_phy);
-		dev_err(xudc->dev, "failed to get usb3 phy: %d\n", err);
-		goto disable_regulator;
-	}
-
-	xudc->utmi_phy = devm_phy_optional_get(&pdev->dev, "usb2");
-	if (IS_ERR(xudc->utmi_phy)) {
-		err = PTR_ERR(xudc->utmi_phy);
-		dev_err(xudc->dev, "failed to get usb2 phy: %d\n", err);
+	err = tegra_xudc_phy_get(xudc);
+	if (err)
 		goto disable_regulator;
-	}
 
 	err = tegra_xudc_powerdomain_init(xudc);
 	if (err)
@@ -3601,16 +3714,6 @@ static int tegra_xudc_probe(struct platform_device *pdev)
 	INIT_DELAYED_WORK(&xudc->port_reset_war_work,
 				tegra_xudc_port_reset_war_work);
 
-	xudc->vbus_nb.notifier_call = tegra_xudc_vbus_notifier;
-	xudc->usbphy = devm_usb_get_phy_by_node(xudc->dev,
-						xudc->utmi_phy->dev.of_node,
-						&xudc->vbus_nb);
-	if (IS_ERR(xudc->usbphy)) {
-		err = PTR_ERR(xudc->usbphy);
-		dev_err(xudc->dev, "failed to get usbphy phy: %d\n", err);
-		goto free_eps;
-	}
-
 	pm_runtime_enable(&pdev->dev);
 
 	xudc->gadget.ops = &tegra_xudc_gadget_ops;
@@ -3645,6 +3748,7 @@ static int tegra_xudc_probe(struct platform_device *pdev)
 static int tegra_xudc_remove(struct platform_device *pdev)
 {
 	struct tegra_xudc *xudc = platform_get_drvdata(pdev);
+	int i;
 
 	pm_runtime_get_sync(xudc->dev);
 
@@ -3660,8 +3764,10 @@ static int tegra_xudc_remove(struct platform_device *pdev)
 
 	regulator_bulk_disable(xudc->soc->num_supplies, xudc->supplies);
 
-	phy_power_off(xudc->utmi_phy);
-	phy_power_off(xudc->usb3_phy);
+	for (i = 0; i < xudc->soc->num_phys; i++) {
+		phy_power_off(xudc->utmi_phy[i]);
+		phy_power_off(xudc->usb3_phy[i]);
+	}
 
 	tegra_xudc_phy_exit(xudc);
 
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 13/18] arm64: tegra: update OTG port entries for jetson-tx1
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (11 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 12/18] usb: gadget: tegra-xudc: support multiple device modes Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 14/18] arm64: tegra: update OTG port entries for jetson-tx2 Nagarjuna Kristam
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Populate OTG vbus regulator. Add usb-role-switch entry to USB 2-0 port
and corresponding connector details.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index b009507..18c0610 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1336,7 +1336,6 @@
 		       <&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
 		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", "usb3-0",
 			    "usb3-1";
-
 		dvddio-pex-supply = <&vdd_pex_1v05>;
 		hvddio-pex-supply = <&vdd_1v8>;
 		avdd-usb-supply = <&vdd_3v3_sys>;
@@ -1440,7 +1439,19 @@
 		ports {
 			usb2-0 {
 				status = "okay";
+				vbus-supply = <&vdd_usb_vbus_otg>;
 				mode = "otg";
+
+				usb-role-switch;
+				connector {
+					compatible = "usb-b-connector",
+						     "gpio-usb-b-connector";
+					label = "micro-USB";
+					type = "micro";
+					vbus-gpio = <&gpio TEGRA_GPIO(Z, 0)
+						     GPIO_ACTIVE_LOW>;
+					id-gpio = <&pmic 0 0>;
+				};
 			};
 
 			usb2-1 {
@@ -1606,6 +1617,17 @@
 			vin-supply = <&vdd_5v0_sys>;
 		};
 
+		vdd_usb_vbus_otg: regulator@11 {
+			compatible = "regulator-fixed";
+			reg = <9>;
+			regulator-name = "USB_VBUS_EN0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_5v0_sys>;
+		};
+
 		vdd_hdmi: regulator@10 {
 			compatible = "regulator-fixed";
 			reg = <10>;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 14/18] arm64: tegra: update OTG port entries for jetson-tx2
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (12 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 13/18] arm64: tegra: update OTG port entries for jetson-tx1 Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 15/18] arm64: tegra: Add xudc node for Tegra210 Nagarjuna Kristam
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Add usb-role-switch entry to OTG usb port and add corresponding connector
details.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
index f1de4ff..a1dcdb9 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
@@ -174,8 +174,20 @@
 			usb2-0 {
 				status = "okay";
 				mode = "otg";
-
 				vbus-supply = <&vdd_usb0>;
+
+				usb-role-switch;
+				connector {
+					compatible = "usb-b-connector",
+						     "gpio-usb-b-connector";
+					label = "micro-USB";
+					type = "micro";
+					vbus-gpio = <&gpio
+						     TEGRA186_MAIN_GPIO(X, 7)
+						     GPIO_ACTIVE_LOW>;
+					id-gpio = <&pmic 0 GPIO_ACTIVE_HIGH>;
+				};
+
 			};
 
 			usb2-1 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 15/18] arm64: tegra: Add xudc node for Tegra210
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (13 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 14/18] arm64: tegra: update OTG port entries for jetson-tx2 Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 16/18] arm64: tegra: Enable xudc on Jetson TX1 Nagarjuna Kristam
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Tegra210 has one XUSB device mode controller, which can be operated
HS and SS modes. Add DT entry for XUSB device mode controller.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - Updated clocks and clock-names sequence as per change in bindings doc.
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 48c6325..dfce47b 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -1207,6 +1207,25 @@
 		status = "disabled";
 	};
 
+	usb@700d0000 {
+		compatible = "nvidia,tegra210-xudc";
+		reg = <0x0 0x700d0000 0x0 0x8000>,
+		      <0x0 0x700d8000 0x0 0x1000>,
+		      <0x0 0x700d9000 0x0 0x1000>;
+		reg-names = "base", "fpci", "ipfs";
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA210_CLK_XUSB_DEV>,
+			 <&tegra_car TEGRA210_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA210_CLK_XUSB_SSP_SRC>,
+			 <&tegra_car TEGRA210_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA210_CLK_XUSB_HS_SRC>;
+		clock-names = "dev", "ss", "ss_src", "fs_src", "hs_src";
+		power-domains = <&pd_xusbdev>, <&pd_xusbss>;
+		power-domain-names = "dev", "ss";
+		nvidia,xusb-padctl = <&padctl>;
+		status = "disabled";
+	};
+
 	mipi: mipi@700e3000 {
 		compatible = "nvidia,tegra210-mipi";
 		reg = <0x0 0x700e3000 0x0 0x100>;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 16/18] arm64: tegra: Enable xudc on Jetson TX1
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (14 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 15/18] arm64: tegra: Add xudc node for Tegra210 Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 17/18] arm64: tegra: Add xudc node for Tegra186 Nagarjuna Kristam
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Enable XUSB device mode driver for USB 2-0 slot on Jetson TX1.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index 18c0610..49a2a82 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1361,7 +1361,7 @@
 				status = "okay";
 
 				lanes {
-					usb2-0 {
+					micro_b: usb2-0 {
 						nvidia,function = "xusb";
 						status = "okay";
 					};
@@ -1494,6 +1494,14 @@
 		vmmc-supply = <&vdd_3v3_sd>;
 	};
 
+	usb@700d0000 {
+		status = "okay";
+		phys = <&micro_b>;
+		phy-names = "usb2-0";
+		avddio-usb-supply = <&vdd_3v3_sys>;
+		hvdd-usb-supply = <&vdd_1v8>;
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 17/18] arm64: tegra: Add xudc node for Tegra186
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (15 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 16/18] arm64: tegra: Enable xudc on Jetson TX1 Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-18  9:16 ` [Patch V2 18/18] arm64: tegra: Enable xudc node on Jetson TX2 Nagarjuna Kristam
  2019-12-19 13:13 ` [Patch V2 00/18] Tegra XUSB OTG support Thierry Reding
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Tegra186 has one XUSB device mode controller, which can be operated
HS and SS modes. Add DT entry for XUSB device mode controller.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 7893d78..6da9d09 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -554,6 +554,25 @@
 		#size-cells = <0>;
 	};
 
+	usb@3550000 {
+		compatible = "nvidia,tegra186-xudc";
+		reg = <0x0 0x03550000 0x0 0x8000>,
+		      <0x0 0x03558000 0x0 0x1000>;
+		reg-names = "base", "fpci";
+		interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_XUSB_CORE_DEV>,
+			 <&bpmp TEGRA186_CLK_XUSB_SS>,
+			 <&bpmp TEGRA186_CLK_XUSB_CORE_SS>,
+			 <&bpmp TEGRA186_CLK_XUSB_FS>;
+		clock-names = "dev", "ss", "ss_src", "fs_src";
+		iommus = <&smmu TEGRA186_SID_XUSB_DEV>;
+		power-domains = <&bpmp TEGRA186_POWER_DOMAIN_XUSBB>,
+				<&bpmp TEGRA186_POWER_DOMAIN_XUSBA>;
+		power-domain-names = "dev", "ss";
+		nvidia,xusb-padctl = <&padctl>;
+		status = "disabled";
+	};
+
 	fuse@3820000 {
 		compatible = "nvidia,tegra186-efuse";
 		reg = <0x0 0x03820000 0x0 0x10000>;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch V2 18/18] arm64: tegra: Enable xudc node on Jetson TX2
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (16 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 17/18] arm64: tegra: Add xudc node for Tegra186 Nagarjuna Kristam
@ 2019-12-18  9:16 ` Nagarjuna Kristam
  2019-12-19 13:13 ` [Patch V2 00/18] Tegra XUSB OTG support Thierry Reding
  18 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-18  9:16 UTC (permalink / raw)
  To: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel, Nagarjuna Kristam

Enable XUSB device mode driver for USB 2-0 slot on Jetson TX2.

Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
---
V2:
 - No changes in this version
---
 arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
index a1dcdb9..d7628f5 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
@@ -131,7 +131,7 @@
 				status = "okay";
 
 				lanes {
-					usb2-0 {
+					micro_b: usb2-0 {
 						nvidia,function = "xusb";
 						status = "okay";
 					};
@@ -213,6 +213,13 @@
 		phy-names = "usb2-0", "usb2-1", "usb3-0";
 	};
 
+	usb@3550000 {
+		status = "okay";
+
+		phys = <&micro_b>;
+		phy-names = "usb2-0";
+	};
+
 	i2c@c250000 {
 		/* carrier board ID EEPROM */
 		eeprom@57 {
-- 
2.7.4


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding
  2019-12-18  9:16 ` [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding Nagarjuna Kristam
@ 2019-12-18 23:24   ` Rob Herring
  2019-12-19 13:10   ` Thierry Reding
  1 sibling, 0 replies; 37+ messages in thread
From: Rob Herring @ 2019-12-18 23:24 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: balbi, gregkh, thierry.reding, jonathanh, mark.rutland, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

On Wed, Dec 18, 2019 at 02:46:15PM +0530, Nagarjuna Kristam wrote:
> Add device-tree binding documentation for the XUSB device mode controller
> present on Tegra210 and Tegra186 SoC. This controller supports the USB 3.0
> specification.
> 
> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> ---
> V2:
>  - used enum instead of oneOf and const.
>  - Moved reg, reg-names, clocks, clock-names to property section from allOf.
>  - Limited allOf to min and max items based on soc.
>  - Updated description for power-domains.
>  - Added V1 reference
> ---
> V1
>  - This document is yaml version of [1], with difference of usb-role-switch
>    removal.
> [1] https://patchwork.kernel.org/patch/11156253/ 
> ---
>  .../devicetree/bindings/usb/nvidia,tegra-xudc.yaml | 190 +++++++++++++++++++++
>  1 file changed, 190 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch
  2019-12-18  9:16 ` [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch Nagarjuna Kristam
@ 2019-12-19 13:05   ` Thierry Reding
  2019-12-20  8:08     ` JC Kuo
  0 siblings, 1 reply; 37+ messages in thread
From: Thierry Reding @ 2019-12-19 13:05 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1528 bytes --]

On Wed, Dec 18, 2019 at 02:46:14PM +0530, Nagarjuna Kristam wrote:
> Add usb-role-switch property for Tegra210 and Tegra186 platforms. This
> entry is used by XUSB pad controller driver to register for role changes
> for OTG/Peripheral capable USB 2 ports.
> 
> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> ---
> V2:
>  - Moved usb-role-switch to seperate Required section as suggested by Thierry.
>  - Added reference to usb/usb-conn-gpio.txt for connector subnode.
> ---
>  .../devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt         | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> index 9fb682e..23bf354 100644
> --- a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> @@ -174,6 +174,12 @@ Required properties:
>    - "device": for USB device mode
>    - "otg": for USB OTG mode
>  
> +Required properties for OTG/Peripheral capable USB2 ports:
> +- usb-role-switch: Boolean property to indicate that the port support OTG or

"supports", and also, why if it supports OTG *or* peripheral? Doesn't
OTG imply peripheral? OTG means it can be either peripheral or host,
right? So I think the end of that sentence can be just:

	"... the port supports OTG."

Otherwise:

Acked-by: Thierry Reding <treding@nvidia.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding
  2019-12-18  9:16 ` [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding Nagarjuna Kristam
  2019-12-18 23:24   ` Rob Herring
@ 2019-12-19 13:10   ` Thierry Reding
  1 sibling, 0 replies; 37+ messages in thread
From: Thierry Reding @ 2019-12-19 13:10 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 987 bytes --]

On Wed, Dec 18, 2019 at 02:46:15PM +0530, Nagarjuna Kristam wrote:
> Add device-tree binding documentation for the XUSB device mode controller
> present on Tegra210 and Tegra186 SoC. This controller supports the USB 3.0
> specification.
> 
> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> ---
> V2:
>  - used enum instead of oneOf and const.
>  - Moved reg, reg-names, clocks, clock-names to property section from allOf.
>  - Limited allOf to min and max items based on soc.
>  - Updated description for power-domains.
>  - Added V1 reference
> ---
> V1
>  - This document is yaml version of [1], with difference of usb-role-switch
>    removal.
> [1] https://patchwork.kernel.org/patch/11156253/ 
> ---
>  .../devicetree/bindings/usb/nvidia,tegra-xudc.yaml | 190 +++++++++++++++++++++
>  1 file changed, 190 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml

Acked-by: Thierry Reding <treding@nvidia.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 00/18] Tegra XUSB OTG support
  2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
                   ` (17 preceding siblings ...)
  2019-12-18  9:16 ` [Patch V2 18/18] arm64: tegra: Enable xudc node on Jetson TX2 Nagarjuna Kristam
@ 2019-12-19 13:13 ` Thierry Reding
  2019-12-20  7:35   ` JC Kuo
  18 siblings, 1 reply; 37+ messages in thread
From: Thierry Reding @ 2019-12-19 13:13 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4083 bytes --]

On Wed, Dec 18, 2019 at 02:46:13PM +0530, Nagarjuna Kristam wrote:
> This patch series adds OTG support on XUSB hardware used in Tegra210 and
> Tegra186 SoCs.
> 
> This patchset is composed with :
>  - dt bindings of XUSB Pad Controller
>  - dt bindings for XUSB device Driver
>  - Tegra PHY driver for usb-role-switch and usb-phy
>  - Tegra XUSB host mode driver to support OTG mode
>  - Tegra XUSB device mode driver to use usb-phy and multi device mode
>  - dts for XUSB pad controller
>  - dts for xudc
> 
> Tegra Pad controller driver register for role switch updates for
> OTG/peripheral capable USB ports and adds usb-phy for that corresponding
> USB ports.
> 
> Host and Device mode drivers gets usb-phy from USB2's phy and registers
> notifier for role changes to perform corresponding role tasks.
> 
> Tests done:
>  - device mode support using micro-B USB cable connection between ubuntu
>    host and DUT on micro-B port
>  - host mode support by connecting pen-drive to micro USB port on DUT
>    using micro-B OTG cable.
>  - toggling between these 2 modes by hot plugging corresponding cables.

Are there any tests we can run without manual intervention? Can we force
the device into peripheral mode and then setup a configuration using
configfs? I'm not sure how useful that would be since it doesn't really
exercise the driver code very much and doesn't tell whether it's
actually working.

Any other way how we can test this?

Thierry

> 
> DUT: Jetson-tx1, Jetson tx2.
> 
> V2:
>  - Updated usb-role-switch documentation for Padctl driver.
>  - Update XUDC bindings doc as suggested by Rob.
>  - Used standard error codes for error return.
>  - Added of_platform_depopulate during error and driver removal.
>  - Updated error variable during phy initialization in XUDC driver.
>  - Updated Tegra210 soc dtb file as per changes to binding doc.
> 
> Nagarjuna Kristam (18):
>   dt-bindings: phy: tegra-xusb: Add usb-role-switch
>   dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding
>   phy: tegra: xusb: Add usb-role-switch support
>   phy: tegra: xusb: Add usb-phy support
>   phy: tegra: xusb: Add support to get companion USB 3 port
>   phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210
>   phy: tegra: xusb: Add set_mode support for utmi phy on Tegra186
>   usb: xhci-tegra: Add OTG support
>   usb: gadget: tegra-xudc: Remove usb-role-switch support
>   usb: gadget: tegra-xudc: Add usb-phy support
>   usb: gadget: tegra-xudc: use phy_set_mode to set/unset device mode
>   usb: gadget: tegra-xudc: support multiple device modes
>   arm64: tegra: update OTG port entries for jetson-tx1
>   arm64: tegra: update OTG port entries for jetson-tx2
>   arm64: tegra: Add xudc node for Tegra210
>   arm64: tegra: Enable xudc on Jetson TX1
>   arm64: tegra: Add xudc node for Tegra186
>   arm64: tegra: Enable xudc node on Jetson TX2
> 
>  .../bindings/phy/nvidia,tegra124-xusb-padctl.txt   |   6 +
>  .../devicetree/bindings/usb/nvidia,tegra-xudc.yaml | 190 ++++++++++++++
>  arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts |  23 +-
>  arch/arm64/boot/dts/nvidia/tegra186.dtsi           |  19 ++
>  arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi     |  34 ++-
>  arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  19 ++
>  drivers/phy/tegra/Kconfig                          |   1 +
>  drivers/phy/tegra/xusb-tegra186.c                  | 109 ++++++--
>  drivers/phy/tegra/xusb-tegra210.c                  | 126 ++++++++--
>  drivers/phy/tegra/xusb.c                           | 134 ++++++++++
>  drivers/phy/tegra/xusb.h                           |   5 +
>  drivers/usb/gadget/udc/tegra-xudc.c                | 276 ++++++++++++++-------
>  drivers/usb/host/xhci-tegra.c                      | 225 ++++++++++++++++-
>  include/linux/phy/tegra/xusb.h                     |   2 +
>  14 files changed, 1031 insertions(+), 138 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml
> 
> -- 
> 2.7.4
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support
  2019-12-18  9:16 ` [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support Nagarjuna Kristam
@ 2019-12-19 13:26   ` Thierry Reding
  2019-12-27  6:39     ` Nagarjuna Kristam
  2019-12-26  6:42   ` JC Kuo
  1 sibling, 1 reply; 37+ messages in thread
From: Thierry Reding @ 2019-12-19 13:26 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 5613 bytes --]

On Wed, Dec 18, 2019 at 02:46:16PM +0530, Nagarjuna Kristam wrote:
> If usb-role-switch property is present in USB 2 port, register
> usb-role-switch to receive usb role changes.
> 
> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> ---
> V2:
>  - Removed dev_set_drvdata for port->dev.
>  - Added of_platform_depopulate during error handling and driver removal.
> ---
>  drivers/phy/tegra/Kconfig |  1 +
>  drivers/phy/tegra/xusb.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/phy/tegra/xusb.h  |  3 +++
>  3 files changed, 46 insertions(+)
> 
> diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig
> index f9817c3..df07c4d 100644
> --- a/drivers/phy/tegra/Kconfig
> +++ b/drivers/phy/tegra/Kconfig
> @@ -2,6 +2,7 @@
>  config PHY_TEGRA_XUSB
>  	tristate "NVIDIA Tegra XUSB pad controller driver"
>  	depends on ARCH_TEGRA
> +	select USB_CONN_GPIO
>  	help
>  	  Choose this option if you have an NVIDIA Tegra SoC.
>  
> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
> index f98ec39..dc00b42 100644
> --- a/drivers/phy/tegra/xusb.c
> +++ b/drivers/phy/tegra/xusb.c
> @@ -523,6 +523,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>  	port->dev.type = &tegra_xusb_port_type;
>  	port->dev.of_node = of_node_get(np);
>  	port->dev.parent = padctl->dev;
> +	port->dev.driver = padctl->dev->driver;
>  
>  	err = dev_set_name(&port->dev, "%s-%u", name, index);
>  	if (err < 0)
> @@ -541,6 +542,10 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>  
>  static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
>  {
> +	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
> +		of_platform_depopulate(&port->dev);
> +		usb_role_switch_unregister(port->usb_role_sw);
> +	}
>  	device_unregister(&port->dev);

Nit: I prefer blank lines after blocks for readability.

>  }
>  
> @@ -551,11 +556,42 @@ static const char *const modes[] = {
>  	[USB_DR_MODE_OTG] = "otg",
>  };
>  
> +static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
> +{
> +	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);

I don't understand what "for role is %d" means here. I think perhaps you
meant to simply say "for role %d"? Also, perhaps add parentheses after
the "%s" to clarify that you're referring to a function.

> +
> +	return 0;
> +}
> +
> +static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
> +{
> +	int err = 0;
> +	struct usb_role_switch_desc role_sx_desc = {
> +					.set = tegra_xusb_role_sw_set,
> +					.fwnode = dev_fwnode(&port->dev),
> +						   };

The indentation here is odd. Use a single tab to indent lines after the
opening { and put the closing } on the same column as "struct". Also,
the above may become more readable if you follow the "inverse Christmas
tree" style of declaring functions, where you order lines by their
length, with the longest line first, like so:

	struct usb_role_switch_desc role_sx_desc = {
		.fwnode = dev_fwnode(&port->dev),
		.set = tegra_xusb_role_sw_set,
	};
	int err = 0;

> +
> +	port->usb_role_sw = usb_role_switch_register(&port->dev,
> +						&role_sx_desc);

&role_sx_desc should be aligned with &port->dev.

> +	if (IS_ERR(port->usb_role_sw)) {
> +		err = PTR_ERR(port->usb_role_sw);
> +		if (err != EPROBE_DEFER)
> +			dev_err(&port->dev, "Failed to register USB role SW: %d",

Error messages typically start with a lowercase letter (at least in this
driver). Also perhaps spell out "switch" above because SW could easily
be confused with "software".

> +				err);

Shouldn't we abort here? Consider the case where this indeed defers
probe. If we don't abort here, the of_platform_populate() below will be
called multiple times. Shouldn't it only be called when we actually
succeed in registering the switch?

Also, looking at usb_role_switch_register(), I don't think it ever can
return -EPROBE_DEFER, so I think you can drop that check and print the
error unconditionally.

Thierry

> +	}
> +
> +	/* populate connector entry */
> +	of_platform_populate(port->dev.of_node, NULL, NULL, &port->dev);
> +
> +	return err;
> +}
> +
>  static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>  {
>  	struct tegra_xusb_port *port = &usb2->base;
>  	struct device_node *np = port->dev.of_node;
>  	const char *mode;
> +	int err;
>  
>  	usb2->internal = of_property_read_bool(np, "nvidia,internal");
>  
> @@ -572,6 +608,12 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>  		usb2->mode = USB_DR_MODE_HOST;
>  	}
>  
> +	if (of_property_read_bool(np, "usb-role-switch")) {
> +		err = tegra_xusb_setup_usb_role_switch(port);
> +		if (err < 0)
> +			return err;
> +	}
> +
>  	usb2->supply = devm_regulator_get(&port->dev, "vbus");
>  	return PTR_ERR_OR_ZERO(usb2->supply);
>  }
> diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
> index da94fcc..9f27899 100644
> --- a/drivers/phy/tegra/xusb.h
> +++ b/drivers/phy/tegra/xusb.h
> @@ -12,6 +12,7 @@
>  #include <linux/workqueue.h>
>  
>  #include <linux/usb/otg.h>
> +#include <linux/usb/role.h>
>  
>  /* legacy entry points for backwards-compatibility */
>  int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev);
> @@ -266,6 +267,8 @@ struct tegra_xusb_port {
>  	struct list_head list;
>  	struct device dev;
>  
> +	struct usb_role_switch *usb_role_sw;
> +
>  	const struct tegra_xusb_port_ops *ops;
>  };
>  
> -- 
> 2.7.4
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 04/18] phy: tegra: xusb: Add usb-phy support
  2019-12-18  9:16 ` [Patch V2 04/18] phy: tegra: xusb: Add usb-phy support Nagarjuna Kristam
@ 2019-12-19 13:37   ` Thierry Reding
  2019-12-27  7:06     ` Nagarjuna Kristam
  0 siblings, 1 reply; 37+ messages in thread
From: Thierry Reding @ 2019-12-19 13:37 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 5382 bytes --]

On Wed, Dec 18, 2019 at 02:46:17PM +0530, Nagarjuna Kristam wrote:
> For USB 2 ports that has usb-role-switch enabled, add usb-phy for
> corresponding USB 2 phy. USB role changes from role switch are then
> updated to corresponding host and device mode drivers via usb-phy notifier
> block.
> 
> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> ---
> V2:
>  - Added dev_set_drvdata for port->dev.
> ---
>  drivers/phy/tegra/xusb.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/phy/tegra/xusb.h |  2 ++
>  2 files changed, 73 insertions(+)
> 
> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
> index dc00b42..5bde8f1 100644
> --- a/drivers/phy/tegra/xusb.c
> +++ b/drivers/phy/tegra/xusb.c
> @@ -533,6 +533,8 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>  	if (err < 0)
>  		goto unregister;
>  
> +	dev_set_drvdata(&port->dev, port);
> +
>  	return 0;
>  
>  unregister:
> @@ -545,6 +547,8 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
>  	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
>  		of_platform_depopulate(&port->dev);
>  		usb_role_switch_unregister(port->usb_role_sw);
> +		cancel_work_sync(&port->usb_phy_work);
> +		usb_remove_phy(&port->usb_phy);
>  	}
>  	device_unregister(&port->dev);
>  }
> @@ -556,16 +560,59 @@ static const char *const modes[] = {
>  	[USB_DR_MODE_OTG] = "otg",
>  };
>  
> +static void tegra_xusb_usb_phy_work(struct work_struct *work)
> +{
> +	struct tegra_xusb_port *port = container_of(work,
> +				struct tegra_xusb_port, usb_phy_work);

Perhaps add a static inline function to cast this? Might not be worth it
since we only need to cast once. In that case, perhaps make this look a
little prettier by aligning arguments on subsequent lines with "work" on
the first line?

> +	enum usb_role role = usb_role_switch_get_role(port->usb_role_sw);
> +
> +	dev_dbg(&port->dev, "%s calling notifier for role %d\n", __func__,
> +		role);
> +
> +	atomic_notifier_call_chain(&port->usb_phy.notifier, role,
> +				   &port->usb_phy);

I'm curious: you use an atomic notifier call chain here but then you
schedule work to call it. Typically you only need to schedule work if
you get notified in atomic context and you need to process the event
outside of the atomic context.

Since these are atomic notifiers, do we really need the work? Or the
other way around: why not use regular notifiers if we're processing them
from non-atomic contexts only anyway?

> +}
> +
>  static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
>  {
> +	struct tegra_xusb_port *port = dev_get_drvdata(dev);
> +
>  	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
>  
> +	schedule_work(&port->usb_phy_work);
> +
> +	return 0;
> +}
> +
> +static int tegra_xusb_set_peripheral(struct usb_otg *otg,
> +					struct usb_gadget *gadget)
> +{
> +	struct tegra_xusb_port *port = container_of(otg->usb_phy,
> +					struct tegra_xusb_port, usb_phy);
> +
> +	if (gadget != NULL)
> +		schedule_work(&port->usb_phy_work);
> +
> +	return 0;
> +}
> +
> +static int tegra_xusb_set_host(struct usb_otg *otg, struct usb_bus *host)
> +{
> +	struct tegra_xusb_port *port = container_of(otg->usb_phy,
> +					struct tegra_xusb_port, usb_phy);
> +
> +	if (host != NULL)
> +		schedule_work(&port->usb_phy_work);
> +
>  	return 0;
>  }
>  
> +
>  static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
>  {
>  	int err = 0;
> +	struct tegra_xusb_lane *lane = tegra_xusb_find_lane(port->padctl,
> +							"usb2", port->index);

You're not properly aligning the arguments here.

Thierry

>  	struct usb_role_switch_desc role_sx_desc = {
>  					.set = tegra_xusb_role_sw_set,
>  					.fwnode = dev_fwnode(&port->dev),
> @@ -578,6 +625,30 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
>  		if (err != EPROBE_DEFER)
>  			dev_err(&port->dev, "Failed to register USB role SW: %d",
>  				err);
> +		return err;
> +	}
> +
> +	INIT_WORK(&port->usb_phy_work, tegra_xusb_usb_phy_work);
> +
> +	port->usb_phy.otg = devm_kzalloc(&port->dev,
> +					 sizeof(struct usb_otg), GFP_KERNEL);
> +	if (!port->usb_phy.otg)
> +		return -ENOMEM;
> +
> +	/*
> +	 * Assign phy dev to usb-phy dev. Host/device drivers can use phy
> +	 * reference to retrieve usb-phy details.
> +	 */
> +	port->usb_phy.dev = &lane->pad->lanes[port->index]->dev;
> +	port->usb_phy.dev->driver = port->padctl->dev->driver;
> +	port->usb_phy.otg->usb_phy = &port->usb_phy;
> +	port->usb_phy.otg->set_peripheral = tegra_xusb_set_peripheral;
> +	port->usb_phy.otg->set_host = tegra_xusb_set_host;
> +
> +	err = usb_add_phy_dev(&port->usb_phy);
> +	if (err < 0) {
> +		dev_err(&port->dev, "Failed to add usbphy: %d\n", err);
> +		return err;
>  	}
>  
>  	/* populate connector entry */
> diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
> index 9f27899..2345657 100644
> --- a/drivers/phy/tegra/xusb.h
> +++ b/drivers/phy/tegra/xusb.h
> @@ -268,6 +268,8 @@ struct tegra_xusb_port {
>  	struct device dev;
>  
>  	struct usb_role_switch *usb_role_sw;
> +	struct work_struct usb_phy_work;
> +	struct usb_phy usb_phy;
>  
>  	const struct tegra_xusb_port_ops *ops;
>  };
> -- 
> 2.7.4
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 00/18] Tegra XUSB OTG support
  2019-12-19 13:13 ` [Patch V2 00/18] Tegra XUSB OTG support Thierry Reding
@ 2019-12-20  7:35   ` JC Kuo
  0 siblings, 0 replies; 37+ messages in thread
From: JC Kuo @ 2019-12-20  7:35 UTC (permalink / raw)
  To: Thierry Reding, Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel



On 12/19/19 9:13 PM, Thierry Reding wrote:
> On Wed, Dec 18, 2019 at 02:46:13PM +0530, Nagarjuna Kristam wrote:
>> This patch series adds OTG support on XUSB hardware used in Tegra210 and
>> Tegra186 SoCs.
>>
>> This patchset is composed with :
>>  - dt bindings of XUSB Pad Controller
>>  - dt bindings for XUSB device Driver
>>  - Tegra PHY driver for usb-role-switch and usb-phy
>>  - Tegra XUSB host mode driver to support OTG mode
>>  - Tegra XUSB device mode driver to use usb-phy and multi device mode
>>  - dts for XUSB pad controller
>>  - dts for xudc
>>
>> Tegra Pad controller driver register for role switch updates for
>> OTG/peripheral capable USB ports and adds usb-phy for that corresponding
>> USB ports.
>>
>> Host and Device mode drivers gets usb-phy from USB2's phy and registers
>> notifier for role changes to perform corresponding role tasks.
>>
>> Tests done:
>>  - device mode support using micro-B USB cable connection between ubuntu
>>    host and DUT on micro-B port
It's a micro-AB port according to Micro USB specifications.

>>  - host mode support by connecting pen-drive to micro USB port on DUT
>>    using micro-B OTG cable.
It's a standard-A to micro-A converter.

>>  - toggling between these 2 modes by hot plugging corresponding cables.
> 
> Are there any tests we can run without manual intervention? Can we force
> the device into peripheral mode and then setup a configuration using
> configfs? I'm not sure how useful that would be since it doesn't really
> exercise the driver code very much and doesn't tell whether it's
> actually working.
> 
> Any other way how we can test this?
> 
I don't think there is a way to test role-swap and host/device driver without
swapping cables. Thanks.

> Thierry
> 
>>
>> DUT: Jetson-tx1, Jetson tx2.
>>
>> V2:
>>  - Updated usb-role-switch documentation for Padctl driver.
>>  - Update XUDC bindings doc as suggested by Rob.
>>  - Used standard error codes for error return.
>>  - Added of_platform_depopulate during error and driver removal.
>>  - Updated error variable during phy initialization in XUDC driver.
>>  - Updated Tegra210 soc dtb file as per changes to binding doc.
>>
>> Nagarjuna Kristam (18):
>>   dt-bindings: phy: tegra-xusb: Add usb-role-switch
>>   dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding
>>   phy: tegra: xusb: Add usb-role-switch support
>>   phy: tegra: xusb: Add usb-phy support
>>   phy: tegra: xusb: Add support to get companion USB 3 port
>>   phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210
>>   phy: tegra: xusb: Add set_mode support for utmi phy on Tegra186
>>   usb: xhci-tegra: Add OTG support
>>   usb: gadget: tegra-xudc: Remove usb-role-switch support
>>   usb: gadget: tegra-xudc: Add usb-phy support
>>   usb: gadget: tegra-xudc: use phy_set_mode to set/unset device mode
>>   usb: gadget: tegra-xudc: support multiple device modes
>>   arm64: tegra: update OTG port entries for jetson-tx1
>>   arm64: tegra: update OTG port entries for jetson-tx2
>>   arm64: tegra: Add xudc node for Tegra210
>>   arm64: tegra: Enable xudc on Jetson TX1
>>   arm64: tegra: Add xudc node for Tegra186
>>   arm64: tegra: Enable xudc node on Jetson TX2
>>
>>  .../bindings/phy/nvidia,tegra124-xusb-padctl.txt   |   6 +
>>  .../devicetree/bindings/usb/nvidia,tegra-xudc.yaml | 190 ++++++++++++++
>>  arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts |  23 +-
>>  arch/arm64/boot/dts/nvidia/tegra186.dtsi           |  19 ++
>>  arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi     |  34 ++-
>>  arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  19 ++
>>  drivers/phy/tegra/Kconfig                          |   1 +
>>  drivers/phy/tegra/xusb-tegra186.c                  | 109 ++++++--
>>  drivers/phy/tegra/xusb-tegra210.c                  | 126 ++++++++--
>>  drivers/phy/tegra/xusb.c                           | 134 ++++++++++
>>  drivers/phy/tegra/xusb.h                           |   5 +
>>  drivers/usb/gadget/udc/tegra-xudc.c                | 276 ++++++++++++++-------
>>  drivers/usb/host/xhci-tegra.c                      | 225 ++++++++++++++++-
>>  include/linux/phy/tegra/xusb.h                     |   2 +
>>  14 files changed, 1031 insertions(+), 138 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.yaml
>>
>> -- 
>> 2.7.4
>>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch
  2019-12-19 13:05   ` Thierry Reding
@ 2019-12-20  8:08     ` JC Kuo
  2020-01-10 11:16       ` Thierry Reding
  0 siblings, 1 reply; 37+ messages in thread
From: JC Kuo @ 2019-12-20  8:08 UTC (permalink / raw)
  To: Thierry Reding, Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel


On 12/19/19 9:05 PM, Thierry Reding wrote:
> On Wed, Dec 18, 2019 at 02:46:14PM +0530, Nagarjuna Kristam wrote:
>> Add usb-role-switch property for Tegra210 and Tegra186 platforms. This
>> entry is used by XUSB pad controller driver to register for role changes
>> for OTG/Peripheral capable USB 2 ports.
>>
>> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
>> ---
>> V2:
>>  - Moved usb-role-switch to seperate Required section as suggested by Thierry.
>>  - Added reference to usb/usb-conn-gpio.txt for connector subnode.
>> ---
>>  .../devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt         | 6 ++++++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
>> index 9fb682e..23bf354 100644
>> --- a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
>> +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
>> @@ -174,6 +174,12 @@ Required properties:
>>    - "device": for USB device mode
>>    - "otg": for USB OTG mode
>>  
>> +Required properties for OTG/Peripheral capable USB2 ports:
>> +- usb-role-switch: Boolean property to indicate that the port support OTG or
> 
> "supports", and also, why if it supports OTG *or* peripheral? Doesn't
> OTG imply peripheral? OTG means it can be either peripheral or host,
> right? So I think the end of that sentence can be just:
> 
> 	"... the port supports OTG."
An USB OTG port is capable of both USB host and peripheral operations. An USB
peripheral port can only act as an USB peripheral.

The micro USB ports found on Jetson TX1/TX2 platforms are micro-AB ports which
should implement both host and peripheral capabilities. We say such ports
support OTG. The micro USB port found on Jetson Nano is a micro-B port which
should implement peripheral capability only. We say such ports support
peripheral, rather than OTG.

Thanks,
JC

> 
> Otherwise:
> 
> Acked-by: Thierry Reding <treding@nvidia.com>
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support
  2019-12-18  9:16 ` [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support Nagarjuna Kristam
  2019-12-19 13:26   ` Thierry Reding
@ 2019-12-26  6:42   ` JC Kuo
  2019-12-27  6:18     ` Nagarjuna Kristam
  1 sibling, 1 reply; 37+ messages in thread
From: JC Kuo @ 2019-12-26  6:42 UTC (permalink / raw)
  To: Nagarjuna Kristam, balbi, gregkh, thierry.reding, jonathanh,
	mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel


On 12/18/19 5:16 PM, Nagarjuna Kristam wrote:
> If usb-role-switch property is present in USB 2 port, register
> usb-role-switch to receive usb role changes.
> 
> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> ---
> V2:
>  - Removed dev_set_drvdata for port->dev.
>  - Added of_platform_depopulate during error handling and driver removal.
> ---
>  drivers/phy/tegra/Kconfig |  1 +
>  drivers/phy/tegra/xusb.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/phy/tegra/xusb.h  |  3 +++
>  3 files changed, 46 insertions(+)
> 
> diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig
> index f9817c3..df07c4d 100644
> --- a/drivers/phy/tegra/Kconfig
> +++ b/drivers/phy/tegra/Kconfig
> @@ -2,6 +2,7 @@
>  config PHY_TEGRA_XUSB
>  	tristate "NVIDIA Tegra XUSB pad controller driver"
>  	depends on ARCH_TEGRA
> +	select USB_CONN_GPIO
>  	help
>  	  Choose this option if you have an NVIDIA Tegra SoC.
>  
> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
> index f98ec39..dc00b42 100644
> --- a/drivers/phy/tegra/xusb.c
> +++ b/drivers/phy/tegra/xusb.c
> @@ -523,6 +523,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>  	port->dev.type = &tegra_xusb_port_type;
>  	port->dev.of_node = of_node_get(np);
>  	port->dev.parent = padctl->dev;
> +	port->dev.driver = padctl->dev->driver;
>  
>  	err = dev_set_name(&port->dev, "%s-%u", name, index);
>  	if (err < 0)
> @@ -541,6 +542,10 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>  
>  static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
>  {
> +	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
> +		of_platform_depopulate(&port->dev);
> +		usb_role_switch_unregister(port->usb_role_sw);
> +	}
>  	device_unregister(&port->dev);
>  }
>  
> @@ -551,11 +556,42 @@ static const char *const modes[] = {
>  	[USB_DR_MODE_OTG] = "otg",
>  };
>  
> +static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
> +{
> +	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
> +
> +	return 0;
> +}
> +
> +static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
> +{
> +	int err = 0;
> +	struct usb_role_switch_desc role_sx_desc = {
> +					.set = tegra_xusb_role_sw_set,
> +					.fwnode = dev_fwnode(&port->dev),
> +						   };
> +
> +	port->usb_role_sw = usb_role_switch_register(&port->dev,
> +						&role_sx_desc);
> +	if (IS_ERR(port->usb_role_sw)) {
> +		err = PTR_ERR(port->usb_role_sw);
> +		if (err != EPROBE_DEFER)
> +			dev_err(&port->dev, "Failed to register USB role SW: %d",
> +				err);
> +	}
> +
> +	/* populate connector entry */
> +	of_platform_populate(port->dev.of_node, NULL, NULL, &port->dev);
> +
> +	return err;
> +}
> +
>  static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>  {
>  	struct tegra_xusb_port *port = &usb2->base;
>  	struct device_node *np = port->dev.of_node;
>  	const char *mode;
> +	int err;
>  
>  	usb2->internal = of_property_read_bool(np, "nvidia,internal");
>  
> @@ -572,6 +608,12 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>  		usb2->mode = USB_DR_MODE_HOST;
>  	}
>  
"usb-role-switch" is not required for host mode port. If a otg or a peripheral
port doesn't have "usb-role-switch" property, .probe() should abort.

Thanks,
JC

> +	if (of_property_read_bool(np, "usb-role-switch")) {
> +		err = tegra_xusb_setup_usb_role_switch(port);
> +		if (err < 0)
> +			return err;
> +	}
> +
>  	usb2->supply = devm_regulator_get(&port->dev, "vbus");
>  	return PTR_ERR_OR_ZERO(usb2->supply);
>  }
> diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
> index da94fcc..9f27899 100644
> --- a/drivers/phy/tegra/xusb.h
> +++ b/drivers/phy/tegra/xusb.h
> @@ -12,6 +12,7 @@
>  #include <linux/workqueue.h>
>  
>  #include <linux/usb/otg.h>
> +#include <linux/usb/role.h>
>  
>  /* legacy entry points for backwards-compatibility */
>  int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev);
> @@ -266,6 +267,8 @@ struct tegra_xusb_port {
>  	struct list_head list;
>  	struct device dev;
>  
> +	struct usb_role_switch *usb_role_sw;
> +
>  	const struct tegra_xusb_port_ops *ops;
>  };
>  
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 05/18] phy: tegra: xusb: Add support to get companion USB 3 port
  2019-12-18  9:16 ` [Patch V2 05/18] phy: tegra: xusb: Add support to get companion USB 3 port Nagarjuna Kristam
@ 2019-12-26  7:03   ` JC Kuo
  0 siblings, 0 replies; 37+ messages in thread
From: JC Kuo @ 2019-12-26  7:03 UTC (permalink / raw)
  To: Nagarjuna Kristam, balbi, gregkh, thierry.reding, jonathanh,
	mark.rutland, robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel


On 12/18/19 5:16 PM, Nagarjuna Kristam wrote:
> Tegra XUSB host, device mode driver requires the USB 3 companion port
> number for corresponding USB 2 port. Add API to retrieve the same.
> 
> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> ---
> V2:
>  - Added -ENODEV as return instead of -1, to sync other errors.
> ---
>  drivers/phy/tegra/xusb.c       | 21 +++++++++++++++++++++
>  include/linux/phy/tegra/xusb.h |  2 ++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
> index 5bde8f1..e75cd71 100644
> --- a/drivers/phy/tegra/xusb.c
> +++ b/drivers/phy/tegra/xusb.c
> @@ -1256,6 +1256,27 @@ int tegra_phy_xusb_utmi_port_reset(struct phy *phy)
>  }
>  EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_port_reset);
>  
> +int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
> +				    unsigned int port)
> +{
> +	struct tegra_xusb_usb2_port *usb2 = tegra_xusb_find_usb2_port(padctl,
> +								      port);
> +	struct tegra_xusb_usb3_port *usb3;
> +	int i;
> +
> +	if (!usb2)
> +		return -EINVAL;
> +
> +	for (i = 0; i < padctl->soc->ports.usb3.count; i++) {
> +		usb3 = tegra_xusb_find_usb3_port(padctl, i);
> +		if (usb3 && usb3->port == usb2->base.index)
> +			return usb3->base.index;
> +	}
> +
> +	return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_usb3_companion);
> +
>  MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
>  MODULE_DESCRIPTION("Tegra XUSB Pad Controller driver");
>  MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/phy/tegra/xusb.h b/include/linux/phy/tegra/xusb.h
> index 1235865..71d9569 100644
> --- a/include/linux/phy/tegra/xusb.h
> +++ b/include/linux/phy/tegra/xusb.h
> @@ -21,4 +21,6 @@ int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl,
>  int tegra_xusb_padctl_set_vbus_override(struct tegra_xusb_padctl *padctl,
>  					bool val);
>  int tegra_phy_xusb_utmi_port_reset(struct phy *phy);
> +int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
> +					 unsigned int port);
>  #endif /* PHY_TEGRA_XUSB_H */
> 
Reviewed-by: JC Kuo <jckuo@nvidia.com>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support
  2019-12-26  6:42   ` JC Kuo
@ 2019-12-27  6:18     ` Nagarjuna Kristam
  0 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-27  6:18 UTC (permalink / raw)
  To: JC Kuo, balbi, gregkh, thierry.reding, jonathanh, mark.rutland,
	robh+dt, kishon
  Cc: devicetree, linux-tegra, linux-usb, linux-kernel



On 26-12-2019 12:12, JC Kuo wrote:
> 
> On 12/18/19 5:16 PM, Nagarjuna Kristam wrote:
>> If usb-role-switch property is present in USB 2 port, register
>> usb-role-switch to receive usb role changes.
>>
>> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
>> ---
>> V2:
>>   - Removed dev_set_drvdata for port->dev.
>>   - Added of_platform_depopulate during error handling and driver removal.
>> ---
>>   drivers/phy/tegra/Kconfig |  1 +
>>   drivers/phy/tegra/xusb.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
>>   drivers/phy/tegra/xusb.h  |  3 +++
>>   3 files changed, 46 insertions(+)
>>
>> diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig
>> index f9817c3..df07c4d 100644
>> --- a/drivers/phy/tegra/Kconfig
>> +++ b/drivers/phy/tegra/Kconfig
>> @@ -2,6 +2,7 @@
>>   config PHY_TEGRA_XUSB
>>   	tristate "NVIDIA Tegra XUSB pad controller driver"
>>   	depends on ARCH_TEGRA
>> +	select USB_CONN_GPIO
>>   	help
>>   	  Choose this option if you have an NVIDIA Tegra SoC.
>>   
>> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
>> index f98ec39..dc00b42 100644
>> --- a/drivers/phy/tegra/xusb.c
>> +++ b/drivers/phy/tegra/xusb.c
>> @@ -523,6 +523,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>>   	port->dev.type = &tegra_xusb_port_type;
>>   	port->dev.of_node = of_node_get(np);
>>   	port->dev.parent = padctl->dev;
>> +	port->dev.driver = padctl->dev->driver;
>>   
>>   	err = dev_set_name(&port->dev, "%s-%u", name, index);
>>   	if (err < 0)
>> @@ -541,6 +542,10 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>>   
>>   static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
>>   {
>> +	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
>> +		of_platform_depopulate(&port->dev);
>> +		usb_role_switch_unregister(port->usb_role_sw);
>> +	}
>>   	device_unregister(&port->dev);
>>   }
>>   
>> @@ -551,11 +556,42 @@ static const char *const modes[] = {
>>   	[USB_DR_MODE_OTG] = "otg",
>>   };
>>   
>> +static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
>> +{
>> +	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
>> +
>> +	return 0;
>> +}
>> +
>> +static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
>> +{
>> +	int err = 0;
>> +	struct usb_role_switch_desc role_sx_desc = {
>> +					.set = tegra_xusb_role_sw_set,
>> +					.fwnode = dev_fwnode(&port->dev),
>> +						   };
>> +
>> +	port->usb_role_sw = usb_role_switch_register(&port->dev,
>> +						&role_sx_desc);
>> +	if (IS_ERR(port->usb_role_sw)) {
>> +		err = PTR_ERR(port->usb_role_sw);
>> +		if (err != EPROBE_DEFER)
>> +			dev_err(&port->dev, "Failed to register USB role SW: %d",
>> +				err);
>> +	}
>> +
>> +	/* populate connector entry */
>> +	of_platform_populate(port->dev.of_node, NULL, NULL, &port->dev);
>> +
>> +	return err;
>> +}
>> +
>>   static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>>   {
>>   	struct tegra_xusb_port *port = &usb2->base;
>>   	struct device_node *np = port->dev.of_node;
>>   	const char *mode;
>> +	int err;
>>   
>>   	usb2->internal = of_property_read_bool(np, "nvidia,internal");
>>   
>> @@ -572,6 +608,12 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>>   		usb2->mode = USB_DR_MODE_HOST;
>>   	}
>>   
> "usb-role-switch" is not required for host mode port. If a otg or a peripheral
> port doesn't have "usb-role-switch" property, .probe() should abort.
> 
> Thanks,
> JC
> 

Yes, will add the checks accordingly.
-nagarjuna

>> +	if (of_property_read_bool(np, "usb-role-switch")) {
>> +		err = tegra_xusb_setup_usb_role_switch(port);
>> +		if (err < 0)
>> +			return err;
>> +	}
>> +
>>   	usb2->supply = devm_regulator_get(&port->dev, "vbus");
>>   	return PTR_ERR_OR_ZERO(usb2->supply);
>>   }
>> diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
>> index da94fcc..9f27899 100644
>> --- a/drivers/phy/tegra/xusb.h
>> +++ b/drivers/phy/tegra/xusb.h
>> @@ -12,6 +12,7 @@
>>   #include <linux/workqueue.h>
>>   
>>   #include <linux/usb/otg.h>
>> +#include <linux/usb/role.h>
>>   
>>   /* legacy entry points for backwards-compatibility */
>>   int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev);
>> @@ -266,6 +267,8 @@ struct tegra_xusb_port {
>>   	struct list_head list;
>>   	struct device dev;
>>   
>> +	struct usb_role_switch *usb_role_sw;
>> +
>>   	const struct tegra_xusb_port_ops *ops;
>>   };
>>   
>>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support
  2019-12-19 13:26   ` Thierry Reding
@ 2019-12-27  6:39     ` Nagarjuna Kristam
  2019-12-29  9:36       ` Thierry Reding
  0 siblings, 1 reply; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-27  6:39 UTC (permalink / raw)
  To: Thierry Reding
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel



On 19-12-2019 18:56, Thierry Reding wrote:
> 
> On Wed, Dec 18, 2019 at 02:46:16PM +0530, Nagarjuna Kristam wrote:
>> If usb-role-switch property is present in USB 2 port, register
>> usb-role-switch to receive usb role changes.
>>
>> Signed-off-by: Nagarjuna Kristam<nkristam@nvidia.com>
>> ---
>> V2:
>>   - Removed dev_set_drvdata for port->dev.
>>   - Added of_platform_depopulate during error handling and driver removal.
>> ---
>>   drivers/phy/tegra/Kconfig |  1 +
>>   drivers/phy/tegra/xusb.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
>>   drivers/phy/tegra/xusb.h  |  3 +++
>>   3 files changed, 46 insertions(+)
>>
>> diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig
>> index f9817c3..df07c4d 100644
>> --- a/drivers/phy/tegra/Kconfig
>> +++ b/drivers/phy/tegra/Kconfig
>> @@ -2,6 +2,7 @@
>>   config PHY_TEGRA_XUSB
>>   	tristate "NVIDIA Tegra XUSB pad controller driver"
>>   	depends on ARCH_TEGRA
>> +	select USB_CONN_GPIO
>>   	help
>>   	  Choose this option if you have an NVIDIA Tegra SoC.
>>   
>> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
>> index f98ec39..dc00b42 100644
>> --- a/drivers/phy/tegra/xusb.c
>> +++ b/drivers/phy/tegra/xusb.c
>> @@ -523,6 +523,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>>   	port->dev.type = &tegra_xusb_port_type;
>>   	port->dev.of_node = of_node_get(np);
>>   	port->dev.parent = padctl->dev;
>> +	port->dev.driver = padctl->dev->driver;
>>   
>>   	err = dev_set_name(&port->dev, "%s-%u", name, index);
>>   	if (err < 0)
>> @@ -541,6 +542,10 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>>   
>>   static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
>>   {
>> +	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
>> +		of_platform_depopulate(&port->dev);
>> +		usb_role_switch_unregister(port->usb_role_sw);
>> +	}
>>   	device_unregister(&port->dev);
> Nit: I prefer blank lines after blocks for readability.
> 
Will update

>>   }
>>   
>> @@ -551,11 +556,42 @@ static const char *const modes[] = {
>>   	[USB_DR_MODE_OTG] = "otg",
>>   };
>>   
>> +static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
>> +{
>> +	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
> I don't understand what "for role is %d" means here. I think perhaps you
> meant to simply say "for role %d"? Also, perhaps add parentheses after
> the "%s" to clarify that you're referring to a function.
> 
Yes, intention is to print role, Will update as mentioned "for role %d"

>> +
>> +	return 0;
>> +}
>> +
>> +static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
>> +{
>> +	int err = 0;
>> +	struct usb_role_switch_desc role_sx_desc = {
>> +					.set = tegra_xusb_role_sw_set,
>> +					.fwnode = dev_fwnode(&port->dev),
>> +						   };
> The indentation here is odd. Use a single tab to indent lines after the
> opening { and put the closing } on the same column as "struct". Also,
> the above may become more readable if you follow the "inverse Christmas
> tree" style of declaring functions, where you order lines by their
> length, with the longest line first, like so:
> 
> 	struct usb_role_switch_desc role_sx_desc = {
> 		.fwnode = dev_fwnode(&port->dev),
> 		.set = tegra_xusb_role_sw_set,
> 	};
> 	int err = 0;
> 
Thanks for inputs, will update accordingly.

>> +
>> +	port->usb_role_sw = usb_role_switch_register(&port->dev,
>> +						&role_sx_desc);
> &role_sx_desc should be aligned with &port->dev.
> 
Will align here and at other places wherever missed.

>> +	if (IS_ERR(port->usb_role_sw)) {
>> +		err = PTR_ERR(port->usb_role_sw);
>> +		if (err != EPROBE_DEFER)
>> +			dev_err(&port->dev, "Failed to register USB role SW: %d",
> Error messages typically start with a lowercase letter (at least in this
> driver). Also perhaps spell out "switch" above because SW could easily
> be confused with "software".
> 
Will update.

>> +				err);
> Shouldn't we abort here? Consider the case where this indeed defers
> probe. If we don't abort here, the of_platform_populate() below will be
> called multiple times. Shouldn't it only be called when we actually
> succeed in registering the switch?
> 
Yes, we should abort here, "return err;" got moved to next patch during
re-base. Will move to current patch.
> Also, looking at usb_role_switch_register(), I don't think it ever can
> return -EPROBE_DEFER, so I think you can drop that check and print the
> error unconditionally.
> 
> Thierry
> 
Will update.
-Nagarjuna
>> +	}
>> +
>> +	/* populate connector entry */
>> +	of_platform_populate(port->dev.of_node, NULL, NULL, &port->dev);
>> +
>> +	return err;
>> +}
>> +
>>   static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>>   {
>>   	struct tegra_xusb_port *port = &usb2->base;
>>   	struct device_node *np = port->dev.of_node;
>>   	const char *mode;
>> +	int err;
>>   
>>   	usb2->internal = of_property_read_bool(np, "nvidia,internal");
>>   
>> @@ -572,6 +608,12 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
>>   		usb2->mode = USB_DR_MODE_HOST;
>>   	}
>>   
>> +	if (of_property_read_bool(np, "usb-role-switch")) {
>> +		err = tegra_xusb_setup_usb_role_switch(port);
>> +		if (err < 0)
>> +			return err;
>> +	}
>> +
>>   	usb2->supply = devm_regulator_get(&port->dev, "vbus");
>>   	return PTR_ERR_OR_ZERO(usb2->supply);
>>   }
>> diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
>> index da94fcc..9f27899 100644
>> --- a/drivers/phy/tegra/xusb.h
>> +++ b/drivers/phy/tegra/xusb.h
>> @@ -12,6 +12,7 @@
>>   #include <linux/workqueue.h>
>>   
>>   #include <linux/usb/otg.h>
>> +#include <linux/usb/role.h>
>>   
>>   /* legacy entry points for backwards-compatibility */
>>   int tegra_xusb_padctl_legacy_probe(struct platform_device *pdev);
>> @@ -266,6 +267,8 @@ struct tegra_xusb_port {
>>   	struct list_head list;
>>   	struct device dev;
>>   
>> +	struct usb_role_switch *usb_role_sw;
>> +
>>   	const struct tegra_xusb_port_ops *ops;
>>   };
>>   
>> -- 
>> 2.7.4

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 04/18] phy: tegra: xusb: Add usb-phy support
  2019-12-19 13:37   ` Thierry Reding
@ 2019-12-27  7:06     ` Nagarjuna Kristam
  0 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-27  7:06 UTC (permalink / raw)
  To: Thierry Reding
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel



On 19-12-2019 19:07, Thierry Reding wrote:
> On Wed, Dec 18, 2019 at 02:46:17PM +0530, Nagarjuna Kristam wrote:
>> For USB 2 ports that has usb-role-switch enabled, add usb-phy for
>> corresponding USB 2 phy. USB role changes from role switch are then
>> updated to corresponding host and device mode drivers via usb-phy notifier
>> block.
>>
>> Signed-off-by: Nagarjuna Kristam<nkristam@nvidia.com>
>> ---
>> V2:
>>   - Added dev_set_drvdata for port->dev.
>> ---
>>   drivers/phy/tegra/xusb.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   drivers/phy/tegra/xusb.h |  2 ++
>>   2 files changed, 73 insertions(+)
>>
>> diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
>> index dc00b42..5bde8f1 100644
>> --- a/drivers/phy/tegra/xusb.c
>> +++ b/drivers/phy/tegra/xusb.c
>> @@ -533,6 +533,8 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
>>   	if (err < 0)
>>   		goto unregister;
>>   
>> +	dev_set_drvdata(&port->dev, port);
>> +
>>   	return 0;
>>   
>>   unregister:
>> @@ -545,6 +547,8 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
>>   	if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
>>   		of_platform_depopulate(&port->dev);
>>   		usb_role_switch_unregister(port->usb_role_sw);
>> +		cancel_work_sync(&port->usb_phy_work);
>> +		usb_remove_phy(&port->usb_phy);
>>   	}
>>   	device_unregister(&port->dev);
>>   }
>> @@ -556,16 +560,59 @@ static const char *const modes[] = {
>>   	[USB_DR_MODE_OTG] = "otg",
>>   };
>>   
>> +static void tegra_xusb_usb_phy_work(struct work_struct *work)
>> +{
>> +	struct tegra_xusb_port *port = container_of(work,
>> +				struct tegra_xusb_port, usb_phy_work);
> Perhaps add a static inline function to cast this? Might not be worth it
> since we only need to cast once. In that case, perhaps make this look a
> little prettier by aligning arguments on subsequent lines with "work" on
> the first line?
> 
Will align arguments with "work".

>> +	enum usb_role role = usb_role_switch_get_role(port->usb_role_sw);
>> +
>> +	dev_dbg(&port->dev, "%s calling notifier for role %d\n", __func__,
>> +		role);
>> +
>> +	atomic_notifier_call_chain(&port->usb_phy.notifier, role,
>> +				   &port->usb_phy);
> I'm curious: you use an atomic notifier call chain here but then you
> schedule work to call it. Typically you only need to schedule work if
> you get notified in atomic context and you need to process the event
> outside of the atomic context.
> 
> Since these are atomic notifiers, do we really need the work? Or the
> other way around: why not use regular notifiers if we're processing them
> from non-atomic contexts only anyway?
> 
notifier used by usb-phy are atomic notifiers and hence need to call
atomic_notifier_call_chain only in this context., regular notifiers
cannot be used.

>> +}
>> +
>>   static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
>>   {
>> +	struct tegra_xusb_port *port = dev_get_drvdata(dev);
>> +
>>   	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
>>   
>> +	schedule_work(&port->usb_phy_work);
>> +
>> +	return 0;
>> +}
>> +
>> +static int tegra_xusb_set_peripheral(struct usb_otg *otg,
>> +					struct usb_gadget *gadget)
>> +{
>> +	struct tegra_xusb_port *port = container_of(otg->usb_phy,
>> +					struct tegra_xusb_port, usb_phy);
>> +
>> +	if (gadget != NULL)
>> +		schedule_work(&port->usb_phy_work);
>> +
>> +	return 0;
>> +}
>> +
>> +static int tegra_xusb_set_host(struct usb_otg *otg, struct usb_bus *host)
>> +{
>> +	struct tegra_xusb_port *port = container_of(otg->usb_phy,
>> +					struct tegra_xusb_port, usb_phy);
>> +
>> +	if (host != NULL)
>> +		schedule_work(&port->usb_phy_work);
>> +
>>   	return 0;
>>   }
>>   
>> +
>>   static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
>>   {
>>   	int err = 0;
>> +	struct tegra_xusb_lane *lane = tegra_xusb_find_lane(port->padctl,
>> +							"usb2", port->index);
> You're not properly aligning the arguments here.
> 
> Thierry
> 
Will align here and other places accordingly.

-Nagarjuna
>>   	struct usb_role_switch_desc role_sx_desc = {
>>   					.set = tegra_xusb_role_sw_set,
>>   					.fwnode = dev_fwnode(&port->dev),
>> @@ -578,6 +625,30 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
>>   		if (err != EPROBE_DEFER)
>>   			dev_err(&port->dev, "Failed to register USB role SW: %d",
>>   				err);
>> +		return err;
>> +	}
>> +
>> +	INIT_WORK(&port->usb_phy_work, tegra_xusb_usb_phy_work);
>> +
>> +	port->usb_phy.otg = devm_kzalloc(&port->dev,
>> +					 sizeof(struct usb_otg), GFP_KERNEL);
>> +	if (!port->usb_phy.otg)
>> +		return -ENOMEM;
>> +
>> +	/*
>> +	 * Assign phy dev to usb-phy dev. Host/device drivers can use phy
>> +	 * reference to retrieve usb-phy details.
>> +	 */
>> +	port->usb_phy.dev = &lane->pad->lanes[port->index]->dev;
>> +	port->usb_phy.dev->driver = port->padctl->dev->driver;
>> +	port->usb_phy.otg->usb_phy = &port->usb_phy;
>> +	port->usb_phy.otg->set_peripheral = tegra_xusb_set_peripheral;
>> +	port->usb_phy.otg->set_host = tegra_xusb_set_host;
>> +
>> +	err = usb_add_phy_dev(&port->usb_phy);
>> +	if (err < 0) {
>> +		dev_err(&port->dev, "Failed to add usbphy: %d\n", err);
>> +		return err;
>>   	}
>>   
>>   	/* populate connector entry */
>> diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
>> index 9f27899..2345657 100644
>> --- a/drivers/phy/tegra/xusb.h
>> +++ b/drivers/phy/tegra/xusb.h
>> @@ -268,6 +268,8 @@ struct tegra_xusb_port {
>>   	struct device dev;
>>   
>>   	struct usb_role_switch *usb_role_sw;
>> +	struct work_struct usb_phy_work;
>> +	struct usb_phy usb_phy;
>>   
>>   	const struct tegra_xusb_port_ops *ops;
>>   };
>> -- 
>> 2.7.4

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support
  2019-12-27  6:39     ` Nagarjuna Kristam
@ 2019-12-29  9:36       ` Thierry Reding
  2019-12-30  5:17         ` Nagarjuna Kristam
  0 siblings, 1 reply; 37+ messages in thread
From: Thierry Reding @ 2019-12-29  9:36 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1164 bytes --]

On Fri, Dec 27, 2019 at 12:09:22PM +0530, Nagarjuna Kristam wrote:
> On 19-12-2019 18:56, Thierry Reding wrote:
> > On Wed, Dec 18, 2019 at 02:46:16PM +0530, Nagarjuna Kristam wrote:
[...]
> > > @@ -551,11 +556,42 @@ static const char *const modes[] = {
> > >   	[USB_DR_MODE_OTG] = "otg",
> > >   };
> > > +static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
> > > +{
> > > +	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
> > I don't understand what "for role is %d" means here. I think perhaps you
> > meant to simply say "for role %d"? Also, perhaps add parentheses after
> > the "%s" to clarify that you're referring to a function.
> > 
> Yes, intention is to print role, Will update as mentioned "for role %d"

It might be better to print the name of the role here because I suspect
very few people know the value of the role defines without looking them
up. I thought there was already a function to return the role name for
a given enum usb_role, but it seems like we only have name -> enum
conversion. Might be worth adding that, but doesn't have to be as part
of this series.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support
  2019-12-29  9:36       ` Thierry Reding
@ 2019-12-30  5:17         ` Nagarjuna Kristam
  0 siblings, 0 replies; 37+ messages in thread
From: Nagarjuna Kristam @ 2019-12-30  5:17 UTC (permalink / raw)
  To: Thierry Reding
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel



On 29-12-2019 15:06, Thierry Reding wrote:
> On Fri, Dec 27, 2019 at 12:09:22PM +0530, Nagarjuna Kristam wrote:
>> On 19-12-2019 18:56, Thierry Reding wrote:
>>> On Wed, Dec 18, 2019 at 02:46:16PM +0530, Nagarjuna Kristam wrote:
> [...]
>>>> @@ -551,11 +556,42 @@ static const char *const modes[] = {
>>>>    	[USB_DR_MODE_OTG] = "otg",
>>>>    };
>>>> +static int tegra_xusb_role_sw_set(struct device *dev, enum usb_role role)
>>>> +{
>>>> +	dev_dbg(dev, "%s calling notifier for role is %d\n", __func__, role);
>>> I don't understand what "for role is %d" means here. I think perhaps you
>>> meant to simply say "for role %d"? Also, perhaps add parentheses after
>>> the "%s" to clarify that you're referring to a function.
>>>
>> Yes, intention is to print role, Will update as mentioned "for role %d"
> It might be better to print the name of the role here because I suspect
> very few people know the value of the role defines without looking them
> up. I thought there was already a function to return the role name for
> a given enum usb_role, but it seems like we only have name -> enum
> conversion. Might be worth adding that, but doesn't have to be as part
> of this series.
> 
> Thierry

Will add a structure to define strings for roles enums, similar to modes
usage in this driver.

-Nagarjuna

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch
  2019-12-20  8:08     ` JC Kuo
@ 2020-01-10 11:16       ` Thierry Reding
  2020-01-13  4:37         ` Nagarjuna Kristam
  0 siblings, 1 reply; 37+ messages in thread
From: Thierry Reding @ 2020-01-10 11:16 UTC (permalink / raw)
  To: JC Kuo
  Cc: Nagarjuna Kristam, balbi, gregkh, jonathanh, mark.rutland,
	robh+dt, kishon, devicetree, linux-tegra, linux-usb,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2498 bytes --]

On Fri, Dec 20, 2019 at 04:08:30PM +0800, JC Kuo wrote:
> 
> On 12/19/19 9:05 PM, Thierry Reding wrote:
> > On Wed, Dec 18, 2019 at 02:46:14PM +0530, Nagarjuna Kristam wrote:
> >> Add usb-role-switch property for Tegra210 and Tegra186 platforms. This
> >> entry is used by XUSB pad controller driver to register for role changes
> >> for OTG/Peripheral capable USB 2 ports.
> >>
> >> Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
> >> ---
> >> V2:
> >>  - Moved usb-role-switch to seperate Required section as suggested by Thierry.
> >>  - Added reference to usb/usb-conn-gpio.txt for connector subnode.
> >> ---
> >>  .../devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt         | 6 ++++++
> >>  1 file changed, 6 insertions(+)
> >>
> >> diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> >> index 9fb682e..23bf354 100644
> >> --- a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> >> +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> >> @@ -174,6 +174,12 @@ Required properties:
> >>    - "device": for USB device mode
> >>    - "otg": for USB OTG mode
> >>  
> >> +Required properties for OTG/Peripheral capable USB2 ports:
> >> +- usb-role-switch: Boolean property to indicate that the port support OTG or
> > 
> > "supports", and also, why if it supports OTG *or* peripheral? Doesn't
> > OTG imply peripheral? OTG means it can be either peripheral or host,
> > right? So I think the end of that sentence can be just:
> > 
> > 	"... the port supports OTG."
> An USB OTG port is capable of both USB host and peripheral operations. An USB
> peripheral port can only act as an USB peripheral.
> 
> The micro USB ports found on Jetson TX1/TX2 platforms are micro-AB ports which
> should implement both host and peripheral capabilities. We say such ports
> support OTG. The micro USB port found on Jetson Nano is a micro-B port which
> should implement peripheral capability only. We say such ports support
> peripheral, rather than OTG.

I the port supports only peripheral mode, why do we need to have a
usb-role-switch property? Shouldn't we in that case have a mode property
with value "device"?

usb-mode-switch is only needed if mode = "otg", isn't it? In all other
cases the functionality is fixed (either host or peripheral) and the
mode cannot be switched.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch
  2020-01-10 11:16       ` Thierry Reding
@ 2020-01-13  4:37         ` Nagarjuna Kristam
  2020-01-13 15:06           ` Thierry Reding
  0 siblings, 1 reply; 37+ messages in thread
From: Nagarjuna Kristam @ 2020-01-13  4:37 UTC (permalink / raw)
  To: Thierry Reding, JC Kuo
  Cc: balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel


On 10-01-2020 16:46, Thierry Reding wrote:
> On Fri, Dec 20, 2019 at 04:08:30PM +0800, JC Kuo wrote:
>> On 12/19/19 9:05 PM, Thierry Reding wrote:
>>> On Wed, Dec 18, 2019 at 02:46:14PM +0530, Nagarjuna Kristam wrote:
>>>> Add usb-role-switch property for Tegra210 and Tegra186 platforms. This
>>>> entry is used by XUSB pad controller driver to register for role changes
>>>> for OTG/Peripheral capable USB 2 ports.
>>>>
>>>> Signed-off-by: Nagarjuna Kristam<nkristam@nvidia.com>
>>>> ---
>>>> V2:
>>>>   - Moved usb-role-switch to seperate Required section as suggested by Thierry.
>>>>   - Added reference to usb/usb-conn-gpio.txt for connector subnode.
>>>> ---
>>>>   .../devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt         | 6 ++++++
>>>>   1 file changed, 6 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
>>>> index 9fb682e..23bf354 100644
>>>> --- a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
>>>> +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
>>>> @@ -174,6 +174,12 @@ Required properties:
>>>>     - "device": for USB device mode
>>>>     - "otg": for USB OTG mode
>>>>   
>>>> +Required properties for OTG/Peripheral capable USB2 ports:
>>>> +- usb-role-switch: Boolean property to indicate that the port support OTG or
>>> "supports", and also, why if it supports OTG*or*  peripheral? Doesn't
>>> OTG imply peripheral? OTG means it can be either peripheral or host,
>>> right? So I think the end of that sentence can be just:
>>>
>>> 	"... the port supports OTG."
>> An USB OTG port is capable of both USB host and peripheral operations. An USB
>> peripheral port can only act as an USB peripheral.
>>
>> The micro USB ports found on Jetson TX1/TX2 platforms are micro-AB ports which
>> should implement both host and peripheral capabilities. We say such ports
>> support OTG. The micro USB port found on Jetson Nano is a micro-B port which
>> should implement peripheral capability only. We say such ports support
>> peripheral, rather than OTG.
> I the port supports only peripheral mode, why do we need to have a
> usb-role-switch property? Shouldn't we in that case have a mode property
> with value "device"?
> 
> usb-mode-switch is only needed if mode = "otg", isn't it? In all other
> cases the functionality is fixed (either host or peripheral) and the
> mode cannot be switched.
> 
> Thierry

usb-role-switch is needed when mode == "otg" or "peripheral".

Device mode is detected via vbus GPIO irrespective of mode being 
peripheral only or OTG.
Host mode is detected via id-gpio, in OTG case.

When mode is peripheral, role changes happens between USB_ROLE_DEVICE 
and USB_ROLE_NONE, which are generally based on Vbus GPIO(hot plug) 
detection.

When mode is otg, role changes happens between USB_ROLE_HOST, 
USB_ROLE_DEVICE and USB_ROLE_NONE, which are detected via id-gpio, 
vbus-gpio and no detection respectively.

-Nagarjuna

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch
  2020-01-13  4:37         ` Nagarjuna Kristam
@ 2020-01-13 15:06           ` Thierry Reding
  0 siblings, 0 replies; 37+ messages in thread
From: Thierry Reding @ 2020-01-13 15:06 UTC (permalink / raw)
  To: Nagarjuna Kristam
  Cc: JC Kuo, balbi, gregkh, jonathanh, mark.rutland, robh+dt, kishon,
	devicetree, linux-tegra, linux-usb, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3551 bytes --]

On Mon, Jan 13, 2020 at 10:07:08AM +0530, Nagarjuna Kristam wrote:
> 
> On 10-01-2020 16:46, Thierry Reding wrote:
> > On Fri, Dec 20, 2019 at 04:08:30PM +0800, JC Kuo wrote:
> > > On 12/19/19 9:05 PM, Thierry Reding wrote:
> > > > On Wed, Dec 18, 2019 at 02:46:14PM +0530, Nagarjuna Kristam wrote:
> > > > > Add usb-role-switch property for Tegra210 and Tegra186 platforms. This
> > > > > entry is used by XUSB pad controller driver to register for role changes
> > > > > for OTG/Peripheral capable USB 2 ports.
> > > > > 
> > > > > Signed-off-by: Nagarjuna Kristam<nkristam@nvidia.com>
> > > > > ---
> > > > > V2:
> > > > >   - Moved usb-role-switch to seperate Required section as suggested by Thierry.
> > > > >   - Added reference to usb/usb-conn-gpio.txt for connector subnode.
> > > > > ---
> > > > >   .../devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt         | 6 ++++++
> > > > >   1 file changed, 6 insertions(+)
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> > > > > index 9fb682e..23bf354 100644
> > > > > --- a/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> > > > > +++ b/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
> > > > > @@ -174,6 +174,12 @@ Required properties:
> > > > >     - "device": for USB device mode
> > > > >     - "otg": for USB OTG mode
> > > > > +Required properties for OTG/Peripheral capable USB2 ports:
> > > > > +- usb-role-switch: Boolean property to indicate that the port support OTG or
> > > > "supports", and also, why if it supports OTG*or*  peripheral? Doesn't
> > > > OTG imply peripheral? OTG means it can be either peripheral or host,
> > > > right? So I think the end of that sentence can be just:
> > > > 
> > > > 	"... the port supports OTG."
> > > An USB OTG port is capable of both USB host and peripheral operations. An USB
> > > peripheral port can only act as an USB peripheral.
> > > 
> > > The micro USB ports found on Jetson TX1/TX2 platforms are micro-AB ports which
> > > should implement both host and peripheral capabilities. We say such ports
> > > support OTG. The micro USB port found on Jetson Nano is a micro-B port which
> > > should implement peripheral capability only. We say such ports support
> > > peripheral, rather than OTG.
> > I the port supports only peripheral mode, why do we need to have a
> > usb-role-switch property? Shouldn't we in that case have a mode property
> > with value "device"?
> > 
> > usb-mode-switch is only needed if mode = "otg", isn't it? In all other
> > cases the functionality is fixed (either host or peripheral) and the
> > mode cannot be switched.
> > 
> > Thierry
> 
> usb-role-switch is needed when mode == "otg" or "peripheral".
> 
> Device mode is detected via vbus GPIO irrespective of mode being peripheral
> only or OTG.
> Host mode is detected via id-gpio, in OTG case.
> 
> When mode is peripheral, role changes happens between USB_ROLE_DEVICE and
> USB_ROLE_NONE, which are generally based on Vbus GPIO(hot plug) detection.
> 
> When mode is otg, role changes happens between USB_ROLE_HOST,
> USB_ROLE_DEVICE and USB_ROLE_NONE, which are detected via id-gpio, vbus-gpio
> and no detection respectively.

Right, that makes perfect sense. Thanks for putting it so clearly. With
the "support" -> "supports" typo fixed, this patch:

Acked-by: Thierry Reding <treding@nvidia.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, back to index

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-18  9:16 [Patch V2 00/18] Tegra XUSB OTG support Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 01/18] dt-bindings: phy: tegra-xusb: Add usb-role-switch Nagarjuna Kristam
2019-12-19 13:05   ` Thierry Reding
2019-12-20  8:08     ` JC Kuo
2020-01-10 11:16       ` Thierry Reding
2020-01-13  4:37         ` Nagarjuna Kristam
2020-01-13 15:06           ` Thierry Reding
2019-12-18  9:16 ` [Patch V2 02/18] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding Nagarjuna Kristam
2019-12-18 23:24   ` Rob Herring
2019-12-19 13:10   ` Thierry Reding
2019-12-18  9:16 ` [Patch V2 03/18] phy: tegra: xusb: Add usb-role-switch support Nagarjuna Kristam
2019-12-19 13:26   ` Thierry Reding
2019-12-27  6:39     ` Nagarjuna Kristam
2019-12-29  9:36       ` Thierry Reding
2019-12-30  5:17         ` Nagarjuna Kristam
2019-12-26  6:42   ` JC Kuo
2019-12-27  6:18     ` Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 04/18] phy: tegra: xusb: Add usb-phy support Nagarjuna Kristam
2019-12-19 13:37   ` Thierry Reding
2019-12-27  7:06     ` Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 05/18] phy: tegra: xusb: Add support to get companion USB 3 port Nagarjuna Kristam
2019-12-26  7:03   ` JC Kuo
2019-12-18  9:16 ` [Patch V2 06/18] phy: tegra: xusb: Add set_mode support for USB 2 phy on Tegra210 Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 07/18] phy: tegra: xusb: Add set_mode support for utmi phy on Tegra186 Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 08/18] usb: xhci-tegra: Add OTG support Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 09/18] usb: gadget: tegra-xudc: Remove usb-role-switch support Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 10/18] usb: gadget: tegra-xudc: Add usb-phy support Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 11/18] usb: gadget: tegra-xudc: use phy_set_mode to set/unset device mode Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 12/18] usb: gadget: tegra-xudc: support multiple device modes Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 13/18] arm64: tegra: update OTG port entries for jetson-tx1 Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 14/18] arm64: tegra: update OTG port entries for jetson-tx2 Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 15/18] arm64: tegra: Add xudc node for Tegra210 Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 16/18] arm64: tegra: Enable xudc on Jetson TX1 Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 17/18] arm64: tegra: Add xudc node for Tegra186 Nagarjuna Kristam
2019-12-18  9:16 ` [Patch V2 18/18] arm64: tegra: Enable xudc node on Jetson TX2 Nagarjuna Kristam
2019-12-19 13:13 ` [Patch V2 00/18] Tegra XUSB OTG support Thierry Reding
2019-12-20  7:35   ` JC Kuo

Linux-USB Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-usb/0 linux-usb/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-usb linux-usb/ https://lore.kernel.org/linux-usb \
		linux-usb@vger.kernel.org
	public-inbox-index linux-usb

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-usb


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git