LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [RFC 00/19] dwc3: add USB OTG role switch support
@ 2015-03-18 14:04 Robert Baldyga
  2015-03-18 14:04 ` [RFC 01/19] extcon: add extcon-odroid-usbotg driver Robert Baldyga
                   ` (19 more replies)
  0 siblings, 20 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Hello,

This patchset introduces OTG feature in DWC3 DRD driver. This allows
to change dynamically between host and peripheral mode depending on
detected USB cable type.

DWC3 driver behaviour is changed only in situation when selected operation
mode (dr_mode) is "otg", and hardware OTG support is available or extended
OTG operations are supplied for given platform.

It such conditions are fulfilled, none of modes is enabled by default
and dwc3 core Best regards,
Robert Baldygais being uninitialized. After USB cable detection relevant
mode is selected and dwc3 core is initialized. Cable disconnection causes
deinitialization of dwc3 core.

File otg.c is inspired by code of DWC3 driver from Hardkernel linux
sources [1]. I have never tested it on DWC3 version equipped with hardware
OTG support, but I belive that this code have chance to work or at least
it's easy to fix. I have tested this on OdroidXU3 board which has USB
cable detection mechanism based on two gpio pins. I used extcon driver
for those feature, which is also attached to following patchset.

I consider if ext_otg_ops it the right solution. Current solution is
based on Hardkernel sources, but it's very likely that adding extcon
support directly to otg.c would be generic enough, as most of cable
detection mechanisms can be simply represented by extcon devices.

Thanks in advance for your comments.

Best regards,
Robert Baldyga

[1] https://github.com/hardkernel/linux

Robert Baldyga (19):
  extcon: add extcon-odroid-usbotg driver
  dt-bindings: extcon: Add doc for extcon-odroid-usbotg
  ARM: dts: exynos5422-odroidxu3: add odroid-usbotg extcon support
  dwc3: gadget: add VBUS session handling
  dwc3: gadget: enable/disable ep0 in dwc3_gadget_run_stop()
  dwc3: gadget: check returned value in suspend/resume
  dwc3: core: cleanup suspend/resume code
  dwc3: core: handle event buffers in core_init/exit
  dwc3: core: make dwc3_core_init/exit non-static
  dwc3: add missing OTG register definitions
  dwc3: add OTG handling code
  dwc3: otg: add ext_otg_ops support
  dwc3: gadget: register gadget in OTG core
  dwc3: host: don't add XHCI device only if in OTG mode
  dwc3: core: initialize OTG in DWC3 core
  dwc3: exynos: add software role switching code
  ARM: dts: exynos5420: set usb3_lpm_capable in dwc3 controllers
  ARM: dts: exynos5420: add snps,dis_u3_susphy_quirk to dwc3 controllers
  ARM: dts: exynos5422-odroidxu3: make usbdrd3 extcon client

 .../bindings/extcon/extcon-odroid-usbotg.txt       |  16 +
 .../devicetree/bindings/usb/exynos-usb.txt         |   4 +
 arch/arm/boot/dts/exynos5420.dtsi                  |   6 +
 arch/arm/boot/dts/exynos5422-odroidxu3.dts         |  24 +
 drivers/extcon/Kconfig                             |   4 +
 drivers/extcon/Makefile                            |   1 +
 drivers/extcon/extcon-odroid-usbotg.c              | 257 +++++++++
 drivers/usb/dwc3/Kconfig                           |   1 +
 drivers/usb/dwc3/Makefile                          |   4 +
 drivers/usb/dwc3/core.c                            |  66 ++-
 drivers/usb/dwc3/core.h                            |  22 +
 drivers/usb/dwc3/dwc3-exynos.c                     | 162 ++++++
 drivers/usb/dwc3/gadget.c                          | 106 ++--
 drivers/usb/dwc3/host.c                            |  10 +-
 drivers/usb/dwc3/otg.c                             | 577 +++++++++++++++++++++
 drivers/usb/dwc3/otg.h                             | 113 ++++
 16 files changed, 1320 insertions(+), 53 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/extcon/extcon-odroid-usbotg.txt
 create mode 100644 drivers/extcon/extcon-odroid-usbotg.c
 create mode 100644 drivers/usb/dwc3/otg.c
 create mode 100644 drivers/usb/dwc3/otg.h

-- 
1.9.1


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

* [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-19  8:50   ` George Cherian
  2015-03-18 14:04 ` [RFC 02/19] dt-bindings: extcon: Add doc for extcon-odroid-usbotg Robert Baldyga
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga, Łukasz Stelmach

This patch adds extcon driver for Odroid U3, U3+ and X boards.
It recognizes type of USB cable connected to Odroid board basing on
two signal lines VBUS_DET and OTG_ID (the second one is present only
on Odroid U3+ board).

Following table of states presents relationship between this signals
and detected cable type:

state    | VBUS_DET |  OTG_ID
-------------------------------
USB      |    H     |    H
USB_HOST |    H     |    L
disconn. |    L     |    H
USB-HOST |    L     |    L

This driver is based on extcon-gpio driver.

Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/extcon/Kconfig                |   4 +
 drivers/extcon/Makefile               |   1 +
 drivers/extcon/extcon-odroid-usbotg.c | 256 ++++++++++++++++++++++++++++++++++
 3 files changed, 261 insertions(+)
 create mode 100644 drivers/extcon/extcon-odroid-usbotg.c

diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 6a1f7de..891dca3 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -93,4 +93,8 @@ config EXTCON_SM5502
 	  Silicon Mitus SM5502. The SM5502 is a USB port accessory
 	  detector and switch.
 
+config EXTCON_ODROID_USBOTG
+	tristate "Extcon Odroid U3, U3+, X and XU USB OTG port"
+	depends on OF_GPIO
+
 endif # MULTISTATE_SWITCH
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 0370b42..514384e 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997)	+= extcon-max8997.o
 obj-$(CONFIG_EXTCON_PALMAS)	+= extcon-palmas.o
 obj-$(CONFIG_EXTCON_RT8973A)	+= extcon-rt8973a.o
 obj-$(CONFIG_EXTCON_SM5502)	+= extcon-sm5502.o
+obj-$(CONFIG_EXTCON_ODROID_USBOTG) += extcon-odroid-usbotg.o
diff --git a/drivers/extcon/extcon-odroid-usbotg.c b/drivers/extcon/extcon-odroid-usbotg.c
new file mode 100644
index 0000000..7f71c48
--- /dev/null
+++ b/drivers/extcon/extcon-odroid-usbotg.c
@@ -0,0 +1,256 @@
+/*
+ *  drivers/extcon/extcon-odroid-usbotg.c
+ *
+ *  USB cable extcon driver for Odroid U3, Odroid U3+ and Odroid X
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ * Author: Lukasz Stelmach <l.stelmach@samsung.com>
+ * Author: Robert Baldyga <r.baldyga@samsung.com>
+ *
+ * based on drivers/extcon/extcon-gpio.c
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/extcon.h>
+#include <linux/extcon/extcon-gpio.h>
+#include <linux/delay.h>
+
+enum {
+	EXTCON_CABLE_USB = 0,
+	EXTCON_CABLE_USB_HOST,
+
+	_EXTCON_CABLE_NUM,
+};
+
+static const char * const odroid_usbotg_cable[] = {
+	[EXTCON_CABLE_USB] = "USB",
+	[EXTCON_CABLE_USB_HOST] = "USB-HOST",
+
+	NULL,
+};
+
+struct odroid_usbotg_data {
+	struct extcon_dev *edev;
+	struct gpio_desc *otg_id;
+	struct gpio_desc *vbus_det;
+	int otg_id_irq;
+	int vbus_det_irq;
+	unsigned long debounce_ms;
+};
+
+/*
+ * state    | VBUS_DET |  OTG_ID
+ * -------------------------------
+ * USB      |    H     |    H
+ * USB-HOST |    H     |    L
+ * disconn. |    L     |    H
+ * USB-HOST |    L     |    L
+ *
+ * Only Odroid U3+ has OTG_ID line. U3 and X versions can detect only
+ * USB slave cable.
+ */
+
+static void odroid_usbotg_detect_cable(struct odroid_usbotg_data *extcon_data)
+{
+	int state;
+
+	mdelay(extcon_data->debounce_ms);
+
+	if (extcon_data->otg_id)
+		state = (gpiod_get_value(extcon_data->vbus_det) << 1) |
+			gpiod_get_value(extcon_data->otg_id);
+	else
+		state = (gpiod_get_value(extcon_data->vbus_det) << 1) | 1;
+
+	dev_dbg(&extcon_data->edev->dev, "cable state changed to %d\n", state);
+
+	if (state & 0x1)
+		extcon_set_cable_state_(extcon_data->edev,
+			EXTCON_CABLE_USB_HOST, false);
+	if (state != 0x3)
+		extcon_set_cable_state_(extcon_data->edev,
+			EXTCON_CABLE_USB, false);
+
+	if (!(state & 0x1))
+		extcon_set_cable_state_(extcon_data->edev,
+			EXTCON_CABLE_USB_HOST, true);
+	else if (state == 0x3)
+		extcon_set_cable_state_(extcon_data->edev,
+			EXTCON_CABLE_USB, true);
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+	struct odroid_usbotg_data *extcon_data = dev_id;
+
+	odroid_usbotg_detect_cable(extcon_data);
+
+	return IRQ_HANDLED;
+}
+
+static int odroid_usbotg_parse_dt(struct platform_device *pdev,
+				    struct odroid_usbotg_data *extcon_data)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 val;
+
+	if (!np)
+		return -ENODEV;
+
+	extcon_data->edev->name = np->name;
+
+	if (of_property_read_u32(np, "debounce", &val) != 0)
+		val = 50;
+	extcon_data->debounce_ms = val;
+
+	return 0;
+}
+
+static int odroid_usbotg_probe(struct platform_device *pdev)
+{
+	struct odroid_usbotg_data *extcon_data;
+	int ret = 0;
+
+	extcon_data = devm_kzalloc(&pdev->dev,
+		sizeof(struct odroid_usbotg_data), GFP_KERNEL);
+	if (!extcon_data)
+		return -ENOMEM;
+
+	extcon_data->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
+					 GFP_KERNEL);
+	if (IS_ERR(extcon_data->edev)) {
+		dev_err(&pdev->dev, "failed to allocate extcon device\n");
+		return -ENOMEM;
+	}
+	extcon_data->edev->supported_cable = odroid_usbotg_cable;
+
+	ret = odroid_usbotg_parse_dt(pdev, extcon_data);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "failed to get data from device tree\n");
+		return ret;
+	}
+
+	/* gpios */
+	extcon_data->vbus_det = devm_gpiod_get(&pdev->dev, "vbus-det");
+	if (IS_ERR(extcon_data->vbus_det)) {
+		dev_err(&pdev->dev, "failed to get vbus_det gpio\n");
+		return PTR_ERR(extcon_data->vbus_det);
+	}
+	extcon_data->otg_id = devm_gpiod_get_optional(&pdev->dev, "otg-id");
+
+	extcon_data->edev->dev.parent = &pdev->dev;
+	ret = extcon_dev_register(extcon_data->edev);
+	if (ret < 0)
+		return ret;
+
+	/* irq */
+	extcon_data->vbus_det_irq = gpiod_to_irq(extcon_data->vbus_det);
+	if (extcon_data->vbus_det_irq < 0) {
+		dev_err(&pdev->dev, "failed to get irq from vbus_det\n");
+		ret = extcon_data->vbus_det_irq;
+		goto err;
+	}
+	ret = request_threaded_irq(extcon_data->vbus_det_irq, NULL,
+				   gpio_irq_handler, IRQF_ONESHOT |
+				   IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				   pdev->name, extcon_data);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to request vbus_det irq\n");
+		goto err;
+	}
+
+	if (extcon_data->otg_id) {
+		extcon_data->otg_id_irq = gpiod_to_irq(extcon_data->otg_id);
+		if (extcon_data->otg_id_irq < 0) {
+			dev_err(&pdev->dev, "failed to get irq from otg_id\n");
+			ret = extcon_data->otg_id_irq;
+			goto err;
+		}
+		ret = request_threaded_irq(extcon_data->otg_id_irq, NULL,
+				gpio_irq_handler, IRQF_ONESHOT |
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				pdev->name, extcon_data);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to request otg_id irq\n");
+			goto err;
+		}
+	}
+
+	platform_set_drvdata(pdev, extcon_data);
+	/* Perform initial detection */
+	odroid_usbotg_detect_cable(extcon_data);
+
+	dev_dbg(&pdev->dev, "probe: success\n");
+
+	return 0;
+
+err:
+	extcon_dev_unregister(extcon_data->edev);
+
+	return ret;
+}
+
+static int odroid_usbotg_remove(struct platform_device *pdev)
+{
+	struct odroid_usbotg_data *extcon_data = platform_get_drvdata(pdev);
+
+	free_irq(extcon_data->vbus_det_irq, extcon_data);
+	if (extcon_data->otg_id)
+		free_irq(extcon_data->otg_id_irq, extcon_data);
+	extcon_dev_unregister(extcon_data->edev);
+
+	return 0;
+}
+
+static const struct of_device_id odroid_usbotg_of_match[] = {
+	{ .compatible = "extcon-odroid-usbotg" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, odroid_usbotg_of_match);
+
+static struct platform_driver odroid_usbotg_driver = {
+	.probe		= odroid_usbotg_probe,
+	.remove		= odroid_usbotg_remove,
+	.driver		= {
+		.name	= "odroid-usbotg",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(odroid_usbotg_of_match)
+	},
+};
+
+static int __init odroid_usbotg_init(void)
+{
+	return platform_driver_register(&odroid_usbotg_driver);
+}
+
+subsys_initcall(odroid_usbotg_init);
+
+static void __exit odroid_usbotg_cleanup(void)
+{
+	platform_driver_unregister(&odroid_usbotg_driver);
+}
+
+module_exit(odroid_usbotg_cleanup);
+
+MODULE_AUTHOR("Lukasz Stelmach <l.stelmach@samsung.com>, Robert Baldyga <r.baldyga@samsung.com>");
+MODULE_DESCRIPTION("USB OTG extcon driver for Odroid U3, U3+ and X");
+MODULE_LICENSE("GPL");
-- 
1.9.1


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

* [RFC 02/19] dt-bindings: extcon: Add doc for extcon-odroid-usbotg
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
  2015-03-18 14:04 ` [RFC 01/19] extcon: add extcon-odroid-usbotg driver Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 03/19] ARM: dts: exynos5422-odroidxu3: add odroid-usbotg extcon support Robert Baldyga
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This patch adds documentation for binding of extcon-odroid-usbotg device
which is using extcon subsystem. This driver allows to detect type of
cable connected to micro-USB port on Odroid boards.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 .../devicetree/bindings/extcon/extcon-odroid-usbotg.txt  | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/extcon/extcon-odroid-usbotg.txt

diff --git a/Documentation/devicetree/bindings/extcon/extcon-odroid-usbotg.txt b/Documentation/devicetree/bindings/extcon/extcon-odroid-usbotg.txt
new file mode 100644
index 0000000..3f24e00
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-odroid-usbotg.txt
@@ -0,0 +1,16 @@
+EXTCON FOR ODROID BOARDS
+
+Required Properties:
+ - compatible: "extcon-odroid-usbotg"
+ - vbus-det-gpio: gpio pin detecting VBUS state
+
+Optional Properties:
+ - otg-id-gpio: gpio pin detecting ID pin on USB cable
+ - debounce: debounce time in milliseconds
+
+Example:
+odroid-extcon {
+	compatible = "extcon-odroid-usbotg";
+	otg-id-gpio = <&gpx1 1 0>;
+	vbus-det-gpio = <&gpx3 4 0>;
+};
-- 
1.9.1


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

* [RFC 03/19] ARM: dts: exynos5422-odroidxu3: add odroid-usbotg extcon support
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
  2015-03-18 14:04 ` [RFC 01/19] extcon: add extcon-odroid-usbotg driver Robert Baldyga
  2015-03-18 14:04 ` [RFC 02/19] dt-bindings: extcon: Add doc for extcon-odroid-usbotg Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 04/19] dwc3: gadget: add VBUS session handling Robert Baldyga
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Add extcon device detecting USB cable type.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 arch/arm/boot/dts/exynos5422-odroidxu3.dts | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index a519c86..80057d6 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -278,6 +278,14 @@
 	rtc@101E0000 {
 		status = "okay";
 	};
+
+	usb_extcon: odroid-usbotg {
+		compatible = "extcon-odroid-usbotg";
+		pinctrl-names = "default";
+		pinctrl-0 = <&otg_id &vbus_det>;
+		otg-id-gpio = <&gpx1 1 0>;
+		vbus-det-gpio = <&gpx3 4 0>;
+	};
 };
 
 &hdmi {
@@ -369,3 +377,15 @@
 		shunt-resistor = <10000>;
 	};
 };
+
+&pinctrl_0 {
+	otg_id: otg-id {
+		samsung,pins = "gpx1-1";
+		samsung,pin-pud = <0>;
+	};
+
+	vbus_det: vbus-det {
+		samsung,pins = "gpx3-4";
+		samsung,pin-pud = <0>;
+	};
+};
-- 
1.9.1


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

* [RFC 04/19] dwc3: gadget: add VBUS session handling
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (2 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 03/19] ARM: dts: exynos5422-odroidxu3: add odroid-usbotg extcon support Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 05/19] dwc3: gadget: enable/disable ep0 in dwc3_gadget_run_stop() Robert Baldyga
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This patch adds .vbus_session callback to usb_gadget_ops. VBUS session
handling is necessary for OTG mode. VBUS control is performed during
OTG finite-state machine state switching.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/core.h   |  1 +
 drivers/usb/dwc3/gadget.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index fdab715..e00d46e 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -828,6 +828,7 @@ struct dwc3 {
 
 	unsigned		tx_de_emphasis_quirk:1;
 	unsigned		tx_de_emphasis:2;
+	unsigned		vbus_session:1;
 };
 
 /* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8946c32..80e43a6 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1475,12 +1475,39 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 	return 0;
 }
 
+static int dwc3_gadget_vbus_session(struct usb_gadget *g, int is_active)
+{
+	struct dwc3 *dwc = gadget_to_dwc(g);
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	/* Mark that the vbus was powered */
+	dwc->vbus_session = !!is_active;
+
+	/*
+	 * Check if upper level usb_gadget_driver was already registered with
+	 * this udc controller driver (if dwc3_gadget_start was called)
+	 */
+	if (dwc->gadget_driver)
+		ret = dwc3_gadget_run_stop(dwc, dwc->vbus_session, false);
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return ret;
+}
+
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
 	unsigned long		flags;
 	int			ret;
 
+	/* Need to wait for vbus_session(on) from otg driver */
+	if (dwc->dotg && !dwc->vbus_session)
+		return 0;
+
 	is_on = !!is_on;
 
 	spin_lock_irqsave(&dwc->lock, flags);
@@ -1657,6 +1684,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
 	.get_frame		= dwc3_gadget_get_frame,
 	.wakeup			= dwc3_gadget_wakeup,
 	.set_selfpowered	= dwc3_gadget_set_selfpowered,
+	.vbus_session		= dwc3_gadget_vbus_session,
 	.pullup			= dwc3_gadget_pullup,
 	.udc_start		= dwc3_gadget_start,
 	.udc_stop		= dwc3_gadget_stop,
-- 
1.9.1


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

* [RFC 05/19] dwc3: gadget: enable/disable ep0 in dwc3_gadget_run_stop()
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (3 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 04/19] dwc3: gadget: add VBUS session handling Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 06/19] dwc3: gadget: check returned value in suspend/resume Robert Baldyga
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This patch adds ep0 enabling and disabling in dwc3_gadget_run_stop().
It's because this function now it used not only for pullup but also
for VBUS session control - feature used by OTG code during role switching.
In case of role switching ep0 have to be reinitialized, so doing it inside
dwc3_gadget_run_stop() function seems to be simplest solution.

This change allowed also to remove ep0 enable/disable code from
suspend/resume functions as this operation is already done by
dwc3_gadget_run_stop(), which is also called there.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/gadget.c | 56 +++++++++++++++++++++++------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 80e43a6..4e73934 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1421,13 +1421,38 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
 	return 0;
 }
 
+static void dwc3_gadget_enable_irq(struct dwc3 *dwc);
+static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
+
 static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 {
 	u32			reg;
 	u32			timeout = 500;
+	int			ret;
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	if (is_on) {
+		ret = __dwc3_gadget_ep_enable(dwc->eps[0],
+			&dwc3_gadget_ep0_desc, NULL, false, false);
+		if (ret) {
+			dev_err(dwc->dev, "failed to enable %s\n",
+				dwc->eps[0]->name);
+			return ret;
+		}
+
+		ret = __dwc3_gadget_ep_enable(dwc->eps[1],
+			&dwc3_gadget_ep0_desc, NULL, false, false);
+		if (ret) {
+			dev_err(dwc->dev, "failed to enable %s\n",
+				dwc->eps[1]->name);
+			__dwc3_gadget_ep_disable(dwc->eps[0]);
+			return ret;
+		}
+
+		/* begin to receive SETUP packets */
+		dwc->ep0state = EP0_SETUP_PHASE;
+		dwc3_ep0_out_start(dwc);
+
 		if (dwc->revision <= DWC3_REVISION_187A) {
 			reg &= ~DWC3_DCTL_TRGTULST_MASK;
 			reg |= DWC3_DCTL_TRGTULST_RX_DET;
@@ -1442,6 +1467,9 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 
 		dwc->pullups_connected = true;
 	} else {
+		__dwc3_gadget_ep_disable(dwc->eps[0]);
+		__dwc3_gadget_ep_disable(dwc->eps[1]);
+
 		reg &= ~DWC3_DCTL_RUN_STOP;
 
 		if (dwc->has_hibernation && !suspend)
@@ -2804,9 +2832,6 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
 		dwc3_gadget_run_stop(dwc, true, true);
 	}
 
-	__dwc3_gadget_ep_disable(dwc->eps[0]);
-	__dwc3_gadget_ep_disable(dwc->eps[1]);
-
 	dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
 
 	return 0;
@@ -2814,28 +2839,9 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
 
 int dwc3_gadget_resume(struct dwc3 *dwc)
 {
-	struct dwc3_ep		*dep;
-	int			ret;
-
 	/* Start with SuperSpeed Default */
 	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
-	dep = dwc->eps[0];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
-			false);
-	if (ret)
-		goto err0;
-
-	dep = dwc->eps[1];
-	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false,
-			false);
-	if (ret)
-		goto err1;
-
-	/* begin to receive SETUP packets */
-	dwc->ep0state = EP0_SETUP_PHASE;
-	dwc3_ep0_out_start(dwc);
-
 	dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
 
 	if (dwc->pullups_connected) {
@@ -2844,10 +2850,4 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
 	}
 
 	return 0;
-
-err1:
-	__dwc3_gadget_ep_disable(dwc->eps[0]);
-
-err0:
-	return ret;
 }
-- 
1.9.1


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

* [RFC 06/19] dwc3: gadget: check returned value in suspend/resume
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (4 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 05/19] dwc3: gadget: enable/disable ep0 in dwc3_gadget_run_stop() Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 07/19] dwc3: core: cleanup suspend/resume code Robert Baldyga
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Check value returned by dwc3_gadget_run_stop() in suspend/resume
functions and propagate it to next layer.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/gadget.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4e73934..b0c1ab5 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2827,18 +2827,22 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
 int dwc3_gadget_suspend(struct dwc3 *dwc)
 {
+	int ret = 0;
+
 	if (dwc->pullups_connected) {
 		dwc3_gadget_disable_irq(dwc);
-		dwc3_gadget_run_stop(dwc, true, true);
+		ret = dwc3_gadget_run_stop(dwc, true, true);
 	}
 
 	dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
 
-	return 0;
+	return ret;
 }
 
 int dwc3_gadget_resume(struct dwc3 *dwc)
 {
+	int ret = 0;
+
 	/* Start with SuperSpeed Default */
 	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
@@ -2846,8 +2850,8 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
 
 	if (dwc->pullups_connected) {
 		dwc3_gadget_enable_irq(dwc);
-		dwc3_gadget_run_stop(dwc, true, false);
+		ret = dwc3_gadget_run_stop(dwc, true, false);
 	}
 
-	return 0;
+	return ret;
 }
-- 
1.9.1


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

* [RFC 07/19] dwc3: core: cleanup suspend/resume code
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (5 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 06/19] dwc3: gadget: check returned value in suspend/resume Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 15:00   ` Sergei Shtylyov
  2015-03-18 14:04 ` [RFC 08/19] dwc3: core: handle event buffers in core_init/exit Robert Baldyga
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Remove unused cases from switch-case statement and place
dwc3_event_buffers_cleanup() function outside switch-case
as it's called in each case anyway.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/core.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 2bbab3d..b040ce0 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1018,13 +1018,12 @@ static int dwc3_suspend(struct device *dev)
 	case USB_DR_MODE_PERIPHERAL:
 	case USB_DR_MODE_OTG:
 		dwc3_gadget_suspend(dwc);
-		/* FALLTHROUGH */
-	case USB_DR_MODE_HOST:
 	default:
-		dwc3_event_buffers_cleanup(dwc);
 		break;
 	}
 
+	dwc3_event_buffers_cleanup(dwc);
+
 	dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1061,10 +1060,7 @@ static int dwc3_resume(struct device *dev)
 	case USB_DR_MODE_PERIPHERAL:
 	case USB_DR_MODE_OTG:
 		dwc3_gadget_resume(dwc);
-		/* FALLTHROUGH */
-	case USB_DR_MODE_HOST:
 	default:
-		/* do nothing */
 		break;
 	}
 
-- 
1.9.1


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

* [RFC 08/19] dwc3: core: handle event buffers in core_init/exit
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (6 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 07/19] dwc3: core: cleanup suspend/resume code Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 09/19] dwc3: core: make dwc3_core_init/exit non-static Robert Baldyga
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This change is part of preparation for OTG feature. Event buffers setup
and cleanup are parts of core_init/exit process, so when core_init/exit
will be called in many places it would be better to have entire procedure
inside these functions instead of calling event_buffers_setup/cleanup
in each place separately.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/core.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index b040ce0..56a4922 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -565,6 +565,12 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	if (ret)
 		goto err2;
 
+	ret = dwc3_event_buffers_setup(dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to setup event buffers\n");
+		goto err2;
+	}
+
 	return 0;
 
 err2:
@@ -582,6 +588,7 @@ err0:
 
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
+	dwc3_event_buffers_cleanup(dwc);
 	dwc3_free_scratch_buffers(dwc);
 	usb_phy_shutdown(dwc->usb2_phy);
 	usb_phy_shutdown(dwc->usb3_phy);
@@ -925,31 +932,22 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err3;
 
-	ret = dwc3_event_buffers_setup(dwc);
-	if (ret) {
-		dev_err(dwc->dev, "failed to setup event buffers\n");
-		goto err4;
-	}
-
 	ret = dwc3_core_init_mode(dwc);
 	if (ret)
-		goto err5;
+		goto err4;
 
 	ret = dwc3_debugfs_init(dwc);
 	if (ret) {
 		dev_err(dev, "failed to initialize debugfs\n");
-		goto err6;
+		goto err5;
 	}
 
 	pm_runtime_allow(dev);
 
 	return 0;
 
-err6:
-	dwc3_core_exit_mode(dwc);
-
 err5:
-	dwc3_event_buffers_cleanup(dwc);
+	dwc3_core_exit_mode(dwc);
 
 err4:
 	phy_power_off(dwc->usb3_generic_phy);
@@ -990,7 +988,6 @@ static int dwc3_remove(struct platform_device *pdev)
 
 	dwc3_debugfs_exit(dwc);
 	dwc3_core_exit_mode(dwc);
-	dwc3_event_buffers_cleanup(dwc);
 	dwc3_free_event_buffers(dwc);
 
 	usb_phy_set_suspend(dwc->usb2_phy, 1);
-- 
1.9.1


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

* [RFC 09/19] dwc3: core: make dwc3_core_init/exit non-static
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (7 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 08/19] dwc3: core: handle event buffers in core_init/exit Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 10/19] dwc3: add missing OTG register definitions Robert Baldyga
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

These functions will be used to reinitialize core during OTG
role switching, so we need ability to call them from OTG code.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/core.c | 4 ++--
 drivers/usb/dwc3/core.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 56a4922..d519b31 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -436,7 +436,7 @@ static void dwc3_phy_setup(struct dwc3 *dwc)
  *
  * Returns 0 on success otherwise negative errno.
  */
-static int dwc3_core_init(struct dwc3 *dwc)
+int dwc3_core_init(struct dwc3 *dwc)
 {
 	unsigned long		timeout;
 	u32			hwparams4 = dwc->hwparams.hwparams4;
@@ -586,7 +586,7 @@ err0:
 	return ret;
 }
 
-static void dwc3_core_exit(struct dwc3 *dwc)
+void dwc3_core_exit(struct dwc3 *dwc)
 {
 	dwc3_event_buffers_cleanup(dwc);
 	dwc3_free_scratch_buffers(dwc);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index e00d46e..aa2c615 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -979,6 +979,8 @@ struct dwc3_gadget_ep_cmd_params {
 /* prototypes */
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
 int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
+int dwc3_core_init(struct dwc3 *dwc);
+void dwc3_core_exit(struct dwc3 *dwc);
 
 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
-- 
1.9.1


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

* [RFC 10/19] dwc3: add missing OTG register definitions
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (8 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 09/19] dwc3: core: make dwc3_core_init/exit non-static Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 11/19] dwc3: add OTG handling code Robert Baldyga
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Add missing definitions of registers used for OTG handling.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/core.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index aa2c615..be29cb2 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -223,6 +223,7 @@
 
 /* Global HWPARAMS6 Register */
 #define DWC3_GHWPARAMS6_EN_FPGA			(1 << 7)
+#define DWC3_GHWPARAMS6_SRP_SUPPORT		(1 << 10)
 
 /* Device Configuration Register */
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
@@ -381,6 +382,20 @@
 #define DWC3_DEPCMD_TYPE_BULK		2
 #define DWC3_DEPCMD_TYPE_INTR		3
 
+/* OTG Control Register */
+#define DWC3_OTG_OCTL_PERIMODE		(1 << 6)
+#define DWC3_OTG_OCTL_PORTPWR		(1 << 5)
+
+/* OTG Events Register */
+#define DWC3_OEVT_DEVICEMODE			(1 << 31)
+#define DWC3_OEVT_CLEAR_ALL			(~DWC3_OEVT_DEVICEMODE)
+#define DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT		(1 << 24)
+#define DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT		(1 << 8)
+
+/* OTG Status Register */
+#define DWC3_OTG_OSTS_BSESVALID		(1 << 2)
+#define DWC3_OTG_OSTS_CONIDSTS		(1 << 0)
+
 /* Structures */
 
 struct dwc3_trb;
-- 
1.9.1


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

* [RFC 11/19] dwc3: add OTG handling code
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (9 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 10/19] dwc3: add missing OTG register definitions Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-19  7:38   ` George Cherian
  2015-03-18 14:04 ` [RFC 12/19] dwc3: otg: add ext_otg_ops support Robert Baldyga
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This patch introduces OTG support in DWC3 driver. OTG feature is responsible
for dynamic USB role switching (between host and peripheral modes) based
on detected cable type.

Each role switch causes complete core reinitialization. In peripheral
mode UDC device is activated using VBUS session control mechanism. In
host mode the new XHCI device is registered to make bus visible in system.

This code is inspired by DWC3 driver from Hardkernel Linux sources [1].

[1] https://github.com/hardkernel/linux.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/Kconfig  |   1 +
 drivers/usb/dwc3/Makefile |   4 +
 drivers/usb/dwc3/core.h   |   4 +
 drivers/usb/dwc3/otg.c    | 497 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/dwc3/otg.h    |  56 ++++++
 5 files changed, 562 insertions(+)
 create mode 100644 drivers/usb/dwc3/otg.c
 create mode 100644 drivers/usb/dwc3/otg.h

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 827c4f8..d3ae67f 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -34,6 +34,7 @@ config USB_DWC3_GADGET
 config USB_DWC3_DUAL_ROLE
 	bool "Dual Role mode"
 	depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3))
+	select USB_OTG_FSM
 	help
 	  This is the default mode of working of DWC3 controller where
 	  both host and gadget features are enabled.
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 46172f4..7a67ee7 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -15,6 +15,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
 	dwc3-y				+= gadget.o ep0.o
 endif
 
+ifneq ($(filter y,$(CONFIG_USB_DWC3_DUAL_ROLE)),)
+	dwc3-y				+= otg.o
+endif
+
 ifneq ($(CONFIG_DEBUG_FS),)
 	dwc3-y				+= debugfs.o
 endif
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index be29cb2..5f8df7c 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -745,6 +745,8 @@ struct dwc3 {
 	struct dwc3_event_buffer **ev_buffs;
 	struct dwc3_ep		*eps[DWC3_ENDPOINTS_NUM];
 
+	struct dwc3_otg		*dotg;
+
 	struct usb_gadget	gadget;
 	struct usb_gadget_driver *gadget_driver;
 
@@ -844,6 +846,8 @@ struct dwc3 {
 	unsigned		tx_de_emphasis_quirk:1;
 	unsigned		tx_de_emphasis:2;
 	unsigned		vbus_session:1;
+
+	unsigned		needs_reinit:1;
 };
 
 /* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/otg.c b/drivers/usb/dwc3/otg.c
new file mode 100644
index 0000000..708ab22
--- /dev/null
+++ b/drivers/usb/dwc3/otg.c
@@ -0,0 +1,497 @@
+/**
+ * otg.c - DesignWare USB3 DRD Controller OTG
+ *
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Authors: Ido Shayevitz <idos@codeaurora.org>
+ *	    Anton Tikhomirov <av.tikhomirov@samsung.com>
+ *	    Robert Baldyga <r.baldyga@samsung.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+
+#include "core.h"
+#include "otg.h"
+#include "io.h"
+
+static void dwc3_otg_set_host_mode(struct dwc3_otg *dotg)
+{
+	struct dwc3	*dwc = dotg->dwc;
+	u32		reg;
+
+	dwc->needs_reinit = 1;
+
+	if (dotg->regs) {
+		reg = dwc3_readl(dotg->regs, DWC3_OCTL);
+		reg &= ~DWC3_OTG_OCTL_PERIMODE;
+		dwc3_writel(dotg->regs, DWC3_OCTL, reg);
+	} else {
+		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
+	}
+}
+
+static void dwc3_otg_set_peripheral_mode(struct dwc3_otg *dotg)
+{
+	struct dwc3	*dwc = dotg->dwc;
+	u32		reg;
+
+	dwc->needs_reinit = 1;
+
+	if (dotg->regs) {
+		reg = dwc3_readl(dotg->regs, DWC3_OCTL);
+		reg |= DWC3_OTG_OCTL_PERIMODE;
+		dwc3_writel(dotg->regs, DWC3_OCTL, reg);
+	} else {
+		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+	}
+}
+
+static void dwc3_otg_drv_vbus(struct otg_fsm *fsm, int on)
+{
+	struct dwc3_otg	*dotg = container_of(fsm, struct dwc3_otg, fsm);
+	int		ret;
+
+	/* Regulator is not available */
+	if (IS_ERR(dotg->vbus_reg) || !dotg->vbus_reg)
+		return;
+
+	if (on)
+		ret = regulator_enable(dotg->vbus_reg);
+	else
+		ret = regulator_disable(dotg->vbus_reg);
+
+	if (ret)
+		dev_err(dotg->dwc->dev, "Failed to turn Vbus %s\n",
+			on ? "on" : "off");
+}
+
+static int dwc3_otg_start_host(struct otg_fsm *fsm, int on)
+{
+	struct usb_otg	*otg = fsm->otg;
+	struct dwc3_otg	*dotg = container_of(otg, struct dwc3_otg, otg);
+	struct dwc3	*dwc = dotg->dwc;
+	struct device	*dev = dotg->dwc->dev;
+	int		ret;
+
+	if (!dotg->dwc->xhci)
+		return -EINVAL;
+
+	dev_info(dev, "Turn %s host\n", on ? "on" : "off");
+
+	if (on) {
+		pm_runtime_get_sync(dev);
+		dwc3_otg_set_host_mode(dotg);
+		if (dwc->needs_reinit) {
+			ret = dwc3_core_init(dwc);
+			if (ret) {
+				dev_err(dwc->dev, "failed to reinitialize core\n");
+				return ret;
+			}
+			dwc->needs_reinit = 0;
+		}
+		ret = platform_device_add(dwc->xhci);
+		if (ret) {
+			dev_err(dev, "%s: cannot add xhci\n", __func__);
+			return ret;
+		}
+	} else {
+		platform_device_del(dwc->xhci);
+		dwc3_core_exit(dwc);
+		dwc->needs_reinit = 1;
+		pm_runtime_put_sync(dev);
+	}
+
+	return 0;
+}
+
+static int dwc3_otg_start_gadget(struct otg_fsm *fsm, int on)
+{
+	struct usb_otg	*otg = fsm->otg;
+	struct dwc3_otg	*dotg = container_of(otg, struct dwc3_otg, otg);
+	struct dwc3	*dwc = dotg->dwc;
+	struct device	*dev = dotg->dwc->dev;
+	int		ret;
+
+	if (!otg->gadget)
+		return -EINVAL;
+
+	dev_info(dev, "Turn %s gadget %s\n",
+		on ? "on" : "off", otg->gadget->name);
+
+	if (on) {
+		pm_runtime_get_sync(dev);
+		dwc3_otg_set_peripheral_mode(dotg);
+		if (dwc->needs_reinit) {
+			ret = dwc3_core_init(dwc);
+			if (ret) {
+				dev_err(dwc->dev, "failed to reinitialize core\n");
+				return ret;
+			}
+			dwc->needs_reinit = 0;
+		}
+		ret = usb_gadget_vbus_connect(otg->gadget);
+	} else {
+		/*
+		 * Delay VBus OFF signal delivery to not miss Disconnect
+		 * interrupt (80ms is minimum; ascertained by experiment)
+		 */
+		msleep(200);
+
+		ret = usb_gadget_vbus_disconnect(otg->gadget);
+		dwc3_core_exit(dwc);
+		dwc->needs_reinit = 1;
+		pm_runtime_put_sync(dev);
+	}
+
+	return ret;
+}
+
+static struct otg_fsm_ops dwc3_otg_fsm_ops = {
+	.drv_vbus	= dwc3_otg_drv_vbus,
+	.start_host	= dwc3_otg_start_host,
+	.start_gadget	= dwc3_otg_start_gadget,
+};
+
+void dwc3_otg_run_sm(struct otg_fsm *fsm)
+{
+	int	state_changed;
+
+	do {
+		state_changed = otg_statemachine(fsm);
+	} while (state_changed > 0);
+}
+
+/**
+ * dwc3_otg_set_peripheral -  bind/unbind the peripheral controller driver.
+ *
+ * Returns 0 on success otherwise negative errno.
+ */
+static int dwc3_otg_set_peripheral(struct usb_otg *otg,
+				struct usb_gadget *gadget)
+{
+	otg->gadget = gadget;
+	if (!gadget)
+		otg->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static irqreturn_t dwc3_otg_thread_interrupt(int irq, void *_dotg)
+{
+	struct dwc3_otg	*dotg = (struct dwc3_otg *)_dotg;
+
+	dwc3_otg_run_sm(&dotg->fsm);
+
+	return IRQ_HANDLED;
+}
+
+static int dwc3_otg_get_id_state(struct dwc3_otg *dotg)
+{
+	u32	reg = dwc3_readl(dotg->regs, DWC3_OSTS);
+
+	return !!(reg & DWC3_OTG_OSTS_CONIDSTS);
+}
+
+static int dwc3_otg_get_b_sess_state(struct dwc3_otg *dotg)
+{
+	u32	reg = dwc3_readl(dotg->regs, DWC3_OSTS);
+
+	return !!(reg & DWC3_OTG_OSTS_BSESVALID);
+}
+
+/**
+ * dwc3_otg_interrupt - interrupt handler for dwc3 otg events.
+ *
+ * @irq: irq number.
+ * @_dotg: Pointer to dwc3 otg context structure.
+ */
+static irqreturn_t dwc3_otg_interrupt(int irq, void *_dotg)
+{
+	struct dwc3_otg	*dotg = (struct dwc3_otg *)_dotg;
+	struct otg_fsm	*fsm = &dotg->fsm;
+	u32		oevt, handled_events = 0;
+	irqreturn_t	ret = IRQ_NONE;
+
+	oevt = dwc3_readl(dotg->regs, DWC3_OEVT);
+
+	/* ID */
+	if (oevt & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) {
+		fsm->id = dwc3_otg_get_id_state(dotg);
+		handled_events |= DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT;
+	}
+
+	/* VBus */
+	if (oevt & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT) {
+		fsm->b_sess_vld = dwc3_otg_get_b_sess_state(dotg);
+		handled_events |= DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT;
+	}
+
+	if (handled_events) {
+		dwc3_writel(dotg->regs, DWC3_OEVT, handled_events);
+		ret = IRQ_WAKE_THREAD;
+	}
+
+	return ret;
+}
+
+static void dwc3_otg_enable_irq(struct dwc3_otg *dotg)
+{
+	/* Enable only connector ID status & VBUS change events */
+	dwc3_writel(dotg->regs, DWC3_OEVTEN,
+			DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT |
+			DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT);
+}
+
+static void dwc3_otg_disable_irq(struct dwc3_otg *dotg)
+{
+	dwc3_writel(dotg->regs, DWC3_OEVTEN, 0x0);
+}
+
+/**
+ * dwc3_otg_reset - reset dwc3 otg registers.
+ *
+ * @dotg: Pointer to dwc3 otg context structure.
+ */
+static void dwc3_otg_reset(struct dwc3_otg *dotg)
+{
+	/*
+	 * OCFG[2] - OTG-Version = 0
+	 * OCFG[1] - HNPCap = 0
+	 * OCFG[0] - SRPCap = 0
+	 */
+	dwc3_writel(dotg->regs, DWC3_OCFG, 0x0);
+
+	/*
+	 * OCTL[6] - PeriMode = 1
+	 * OCTL[5] - PrtPwrCtl = 0
+	 * OCTL[4] - HNPReq = 0
+	 * OCTL[3] - SesReq = 0
+	 * OCTL[2] - TermSelDLPulse = 0
+	 * OCTL[1] - DevSetHNPEn = 0
+	 * OCTL[0] - HstSetHNPEn = 0
+	 */
+	dwc3_writel(dotg->regs, DWC3_OCTL, DWC3_OTG_OCTL_PERIMODE);
+
+	/* Clear all otg events (interrupts) indications  */
+	dwc3_writel(dotg->regs, DWC3_OEVT, DWC3_OEVT_CLEAR_ALL);
+
+}
+
+/* SysFS interface */
+
+/*
+ * id and b_sess attributes allow to change DRD mode and B-Session state.
+ * Can be used for debug purpose.
+ */
+
+static ssize_t
+dwc3_otg_show_b_sess(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct otg_fsm	*fsm = &dwc->dotg->fsm;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", fsm->b_sess_vld);
+}
+
+static ssize_t
+dwc3_otg_store_b_sess(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct otg_fsm	*fsm = &dwc->dotg->fsm;
+	int		b_sess_vld;
+	int		ret;
+
+	ret = kstrtoint(buf, 0, &b_sess_vld);
+	if (ret < 0)
+		return ret;
+
+	fsm->b_sess_vld = !!b_sess_vld;
+
+	dwc3_otg_run_sm(fsm);
+
+	return n;
+}
+
+static DEVICE_ATTR(b_sess, S_IWUSR | S_IRUSR | S_IRGRP,
+	dwc3_otg_show_b_sess, dwc3_otg_store_b_sess);
+
+static ssize_t
+dwc3_otg_show_id(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct otg_fsm	*fsm = &dwc->dotg->fsm;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", fsm->id);
+}
+
+static ssize_t
+dwc3_otg_store_id(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct otg_fsm	*fsm = &dwc->dotg->fsm;
+	int id;
+	int ret;
+
+	ret = kstrtoint(buf, 0, &id);
+	if (ret < 0)
+		return ret;
+
+	fsm->id = !!id;
+
+	dwc3_otg_run_sm(fsm);
+
+	return n;
+}
+
+static DEVICE_ATTR(id, S_IWUSR | S_IRUSR | S_IRGRP,
+	dwc3_otg_show_id, dwc3_otg_store_id);
+
+static struct attribute *dwc3_otg_attributes[] = {
+	&dev_attr_id.attr,
+	&dev_attr_b_sess.attr,
+	NULL
+};
+
+static const struct attribute_group dwc3_otg_attr_group = {
+	.attrs = dwc3_otg_attributes,
+};
+
+/**
+ * dwc3_otg_start
+ * @dwc: pointer to our controller context structure
+ */
+int dwc3_otg_start(struct dwc3 *dwc)
+{
+	struct dwc3_otg		*dotg = dwc->dotg;
+	struct otg_fsm		*fsm = &dotg->fsm;
+	int			ret;
+
+	if (!dotg)
+		return -ENODEV;
+
+	dotg->regs = dwc->regs;
+
+	dwc3_otg_reset(dotg);
+
+	dotg->fsm.id = dwc3_otg_get_id_state(dotg);
+	dotg->fsm.b_sess_vld = dwc3_otg_get_b_sess_state(dotg);
+
+	dotg->irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	ret = devm_request_threaded_irq(dwc->dev, dotg->irq,
+			dwc3_otg_interrupt,
+			dwc3_otg_thread_interrupt,
+			IRQF_SHARED, "dwc3-otg", dotg);
+	if (ret) {
+		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+				dotg->irq, ret);
+		return ret;
+	}
+
+	dwc3_otg_enable_irq(dotg);
+
+	dwc3_otg_run_sm(fsm);
+
+	return 0;
+}
+
+/**
+ * dwc3_otg_stop
+ * @dwc: pointer to our controller context structure
+ */
+void dwc3_otg_stop(struct dwc3 *dwc)
+{
+	struct dwc3_otg		*dotg = dwc->dotg;
+
+	if (!dotg)
+		return;
+
+	dwc3_otg_disable_irq(dotg);
+	free_irq(dotg->irq, dotg);
+}
+
+/**
+ * dwc3_otg_init - Initializes otg related registers
+ * @dwc: pointer to our controller context structure
+ *
+ * Returns 0 on success otherwise negative errno.
+ */
+int dwc3_otg_init(struct dwc3 *dwc)
+{
+	struct dwc3_otg		*dotg;
+	u32			reg;
+	int			ret = 0;
+
+	/*
+	 * GHWPARAMS6[10] bit is SRPSupport.
+	 * This bit also reflects DWC_USB3_EN_OTG
+	 */
+	reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
+	if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
+		dev_err(dwc->dev, "dwc3_otg address space is not supported\n");
+		return 0;
+	}
+
+	/* Allocate and init otg instance */
+	dotg = devm_kzalloc(dwc->dev, sizeof(struct dwc3_otg), GFP_KERNEL);
+	if (!dotg)
+		return -ENOMEM;
+
+	/* This reference is used by dwc3 modules for checking otg existence */
+	dwc->dotg = dotg;
+	dotg->dwc = dwc;
+
+	dotg->otg.set_peripheral = dwc3_otg_set_peripheral;
+	dotg->otg.set_host = NULL;
+
+	dotg->otg.usb_phy = dwc->usb2_phy;
+
+	mutex_init(&dotg->fsm.lock);
+	dotg->fsm.ops = &dwc3_otg_fsm_ops;
+	dotg->fsm.otg = &dotg->otg;
+
+	dotg->vbus_reg = devm_regulator_get(dwc->dev->parent, "dwc3-vbus");
+	if (IS_ERR(dotg->vbus_reg))
+		dev_info(dwc->dev, "vbus regulator is not available\n");
+
+	ret = sysfs_create_group(&dwc->dev->kobj, &dwc3_otg_attr_group);
+	if (ret)
+		dev_err(dwc->dev, "failed to create dwc3 otg attributes\n");
+
+	return 0;
+}
+
+/**
+ * dwc3_otg_exit
+ * @dwc: pointer to our controller context structure
+ */
+void dwc3_otg_exit(struct dwc3 *dwc)
+{
+	struct dwc3_otg		*dotg = dwc->dotg;
+	u32			reg;
+
+	if (!dotg)
+		return;
+
+	sysfs_remove_group(&dwc->dev->kobj, &dwc3_otg_attr_group);
+	kfree(dotg);
+	dwc->dotg = NULL;
+}
diff --git a/drivers/usb/dwc3/otg.h b/drivers/usb/dwc3/otg.h
new file mode 100644
index 0000000..ffb8f0e
--- /dev/null
+++ b/drivers/usb/dwc3/otg.h
@@ -0,0 +1,56 @@
+/**
+ * otg.h - DesignWare USB3 DRD Controller OTG
+ *
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Authors: Ido Shayevitz <idos@codeaurora.org>
+ *	    Anton Tikhomirov <av.tikhomirov@samsung.com>
+ *	    Robert Baldyga <r.baldyga@samsung.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_USB_DWC3_OTG_H
+#define __LINUX_USB_DWC3_OTG_H
+
+#include <linux/usb/otg-fsm.h>
+
+#include "core.h"
+
+/**
+ * struct dwc3_otg: OTG driver data. Shared by HCD and DCD.
+ * @otg: USB OTG Transceiver structure.
+ * @fsm: OTG Final State Machine.
+ * @dwc: pointer to our controller context structure.
+ * @irq: IRQ number assigned for HSUSB controller.
+ * @regs: ioremapped register base address.
+ * @vbus_reg: Vbus regulator.
+ */
+struct dwc3_otg {
+	struct usb_otg          otg;
+	struct otg_fsm		fsm;
+	struct dwc3             *dwc;
+	int                     irq;
+	void __iomem            *regs;
+
+	struct regulator	*vbus_reg;
+};
+
+int dwc3_otg_start(struct dwc3 *dwc);
+void dwc3_otg_stop(struct dwc3 *dwc);
+int dwc3_otg_init(struct dwc3 *dwc);
+void dwc3_otg_exit(struct dwc3 *dwc);
+
+
+void dwc3_otg_run_sm(struct otg_fsm *fsm);
+
+#endif /* __LINUX_USB_DWC3_OTG_H */
-- 
1.9.1


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

* [RFC 12/19] dwc3: otg: add ext_otg_ops support
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (10 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 11/19] dwc3: add OTG handling code Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 13/19] dwc3: gadget: register gadget in OTG core Robert Baldyga
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This feature allows to use OTG feature with devices which doesn't support
hardware DWC3 OTG. In such situation we can supply own mechanism of cable
detection.

This code is inspired by DWC3 driver from Hardkernel Linux sources [1].

[1] https://github.com/hardkernel/linux.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/otg.c | 89 ++++++++++++++++++++++++++++++++++++++++----------
 drivers/usb/dwc3/otg.h | 48 +++++++++++++++++++++++++++
 2 files changed, 120 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/dwc3/otg.c b/drivers/usb/dwc3/otg.c
index 708ab22..99dfd2c 100644
--- a/drivers/usb/dwc3/otg.c
+++ b/drivers/usb/dwc3/otg.c
@@ -29,6 +29,11 @@
 #include "otg.h"
 #include "io.h"
 
+static struct dwc3_ext_otg_ops *dwc3_otg_rsw_probe(struct dwc3 *dwc)
+{
+	return NULL;
+}
+
 static void dwc3_otg_set_host_mode(struct dwc3_otg *dotg)
 {
 	struct dwc3	*dwc = dotg->dwc;
@@ -388,25 +393,33 @@ int dwc3_otg_start(struct dwc3 *dwc)
 	if (!dotg)
 		return -ENODEV;
 
-	dotg->regs = dwc->regs;
+	if (dotg->ext_otg_ops) {
+		ret = dwc3_ext_otg_start(dotg);
+		if (ret) {
+			dev_err(dwc->dev, "failed to start external OTG\n");
+			return ret;
+		}
+	} else {
+		dotg->regs = dwc->regs;
 
-	dwc3_otg_reset(dotg);
+		dwc3_otg_reset(dotg);
 
-	dotg->fsm.id = dwc3_otg_get_id_state(dotg);
-	dotg->fsm.b_sess_vld = dwc3_otg_get_b_sess_state(dotg);
+		dotg->fsm.id = dwc3_otg_get_id_state(dotg);
+		dotg->fsm.b_sess_vld = dwc3_otg_get_b_sess_state(dotg);
 
-	dotg->irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-	ret = devm_request_threaded_irq(dwc->dev, dotg->irq,
-			dwc3_otg_interrupt,
-			dwc3_otg_thread_interrupt,
-			IRQF_SHARED, "dwc3-otg", dotg);
-	if (ret) {
-		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-				dotg->irq, ret);
-		return ret;
-	}
+		dotg->irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+		ret = devm_request_threaded_irq(dwc->dev, dotg->irq,
+				dwc3_otg_interrupt,
+				dwc3_otg_thread_interrupt,
+				IRQF_SHARED, "dwc3-otg", dotg);
+		if (ret) {
+			dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+					dotg->irq, ret);
+			return ret;
+		}
 
-	dwc3_otg_enable_irq(dotg);
+		dwc3_otg_enable_irq(dotg);
+	}
 
 	dwc3_otg_run_sm(fsm);
 
@@ -424,8 +437,12 @@ void dwc3_otg_stop(struct dwc3 *dwc)
 	if (!dotg)
 		return;
 
-	dwc3_otg_disable_irq(dotg);
-	free_irq(dotg->irq, dotg);
+	if (dotg->ext_otg_ops) {
+		dwc3_ext_otg_stop(dotg);
+	} else {
+		dwc3_otg_disable_irq(dotg);
+		free_irq(dotg->irq, dotg);
+	}
 }
 
 /**
@@ -437,6 +454,7 @@ void dwc3_otg_stop(struct dwc3 *dwc)
 int dwc3_otg_init(struct dwc3 *dwc)
 {
 	struct dwc3_otg		*dotg;
+	struct dwc3_ext_otg_ops	*ops = NULL;
 	u32			reg;
 	int			ret = 0;
 
@@ -447,9 +465,25 @@ int dwc3_otg_init(struct dwc3 *dwc)
 	reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
 	if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
 		dev_err(dwc->dev, "dwc3_otg address space is not supported\n");
+
+		/*
+		 * Some SoCs (e.g. Exynos5) don't have HW OTG, however, some
+		 * boards use simplified role switch (rsw) function based on
+		 * ID/BSes gpio interrupts. As a fall-back try to bind to rsw.
+		 */
+		ops = dwc3_otg_rsw_probe(dwc);
+		if (ops)
+			goto has_ext_otg;
+
+		/*
+		 * No HW OTG support in the core.
+		 * We return 0 to indicate no error, since this is acceptable
+		 * situation, just continue probe the dwc3 driver without otg.
+		 */
 		return 0;
 	}
 
+has_ext_otg:
 	/* Allocate and init otg instance */
 	dotg = devm_kzalloc(dwc->dev, sizeof(struct dwc3_otg), GFP_KERNEL);
 	if (!dotg)
@@ -459,6 +493,8 @@ int dwc3_otg_init(struct dwc3 *dwc)
 	dwc->dotg = dotg;
 	dotg->dwc = dwc;
 
+	dotg->ext_otg_ops = ops;
+
 	dotg->otg.set_peripheral = dwc3_otg_set_peripheral;
 	dotg->otg.set_host = NULL;
 
@@ -472,6 +508,14 @@ int dwc3_otg_init(struct dwc3 *dwc)
 	if (IS_ERR(dotg->vbus_reg))
 		dev_info(dwc->dev, "vbus regulator is not available\n");
 
+	if (dotg->ext_otg_ops) {
+		ret = dwc3_ext_otg_setup(dotg);
+		if (ret) {
+			dev_err(dwc->dev, "failed to setup external OTG\n");
+			return ret;
+		}
+	}
+
 	ret = sysfs_create_group(&dwc->dev->kobj, &dwc3_otg_attr_group);
 	if (ret)
 		dev_err(dwc->dev, "failed to create dwc3 otg attributes\n");
@@ -491,6 +535,17 @@ void dwc3_otg_exit(struct dwc3 *dwc)
 	if (!dotg)
 		return;
 
+	reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
+	if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
+		if (dotg->ext_otg_ops) {
+			dwc3_ext_otg_exit(dotg);
+			goto has_ext_otg;
+		}
+
+		return;
+	}
+
+has_ext_otg:
 	sysfs_remove_group(&dwc->dev->kobj, &dwc3_otg_attr_group);
 	kfree(dotg);
 	dwc->dotg = NULL;
diff --git a/drivers/usb/dwc3/otg.h b/drivers/usb/dwc3/otg.h
index ffb8f0e..4be7165 100644
--- a/drivers/usb/dwc3/otg.h
+++ b/drivers/usb/dwc3/otg.h
@@ -26,6 +26,13 @@
 
 #include "core.h"
 
+struct dwc3_ext_otg_ops {
+	int	(*setup)(struct device *dev, struct otg_fsm *fsm);
+	void	(*exit)(struct device *dev);
+	int	(*start)(struct device *dev);
+	void	(*stop)(struct device *dev);
+};
+
 /**
  * struct dwc3_otg: OTG driver data. Shared by HCD and DCD.
  * @otg: USB OTG Transceiver structure.
@@ -34,6 +41,7 @@
  * @irq: IRQ number assigned for HSUSB controller.
  * @regs: ioremapped register base address.
  * @vbus_reg: Vbus regulator.
+ * @ext_otg_ops: external OTG engine ops.
  */
 struct dwc3_otg {
 	struct usb_otg          otg;
@@ -43,8 +51,48 @@ struct dwc3_otg {
 	void __iomem            *regs;
 
 	struct regulator	*vbus_reg;
+
+	struct dwc3_ext_otg_ops	*ext_otg_ops;
 };
 
+static inline int dwc3_ext_otg_setup(struct dwc3_otg *dotg)
+{
+	struct device *dev = dotg->dwc->dev->parent;
+
+	if (!dotg->ext_otg_ops->setup)
+		return -EOPNOTSUPP;
+	return dotg->ext_otg_ops->setup(dev, &dotg->fsm);
+}
+
+static inline int dwc3_ext_otg_exit(struct dwc3_otg *dotg)
+{
+	struct device *dev = dotg->dwc->dev->parent;
+
+	if (!dotg->ext_otg_ops->exit)
+		return -EOPNOTSUPP;
+	dotg->ext_otg_ops->exit(dev);
+	return 0;
+}
+
+static inline int dwc3_ext_otg_start(struct dwc3_otg *dotg)
+{
+	struct device *dev = dotg->dwc->dev->parent;
+
+	if (!dotg->ext_otg_ops->start)
+		return -EOPNOTSUPP;
+	return dotg->ext_otg_ops->start(dev);
+}
+
+static inline int dwc3_ext_otg_stop(struct dwc3_otg *dotg)
+{
+	struct device *dev = dotg->dwc->dev->parent;
+
+	if (!dotg->ext_otg_ops->stop)
+		return -EOPNOTSUPP;
+	dotg->ext_otg_ops->stop(dev);
+	return 0;
+}
+
 int dwc3_otg_start(struct dwc3 *dwc);
 void dwc3_otg_stop(struct dwc3 *dwc);
 int dwc3_otg_init(struct dwc3 *dwc);
-- 
1.9.1


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

* [RFC 13/19] dwc3: gadget: register gadget in OTG core
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (11 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 12/19] dwc3: otg: add ext_otg_ops support Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 14/19] dwc3: host: don't add XHCI device only if in OTG mode Robert Baldyga
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Gadget driver needs to be registered in OTG to perform dynamic
role switching.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/gadget.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index b0c1ab5..c5a7cf1 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -32,6 +32,7 @@
 
 #include "debug.h"
 #include "core.h"
+#include "otg.h"
 #include "gadget.h"
 #include "io.h"
 
@@ -2783,8 +2784,18 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 		goto err4;
 	}
 
+	if (dwc->dotg) {
+		ret = otg_set_peripheral(&dwc->dotg->otg, &dwc->gadget);
+		if (ret) {
+			dev_err(dwc->dev, "failed to set otg peripheral\n");
+			goto err5;
+		}
+	}
+
 	return 0;
 
+err5:
+	usb_del_gadget_udc(&dwc->gadget);
 err4:
 	dwc3_gadget_free_endpoints(dwc);
 	dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
@@ -2809,6 +2820,9 @@ err0:
 
 void dwc3_gadget_exit(struct dwc3 *dwc)
 {
+	if (dwc->dotg)
+		otg_set_peripheral(&dwc->dotg->otg, NULL);
+
 	usb_del_gadget_udc(&dwc->gadget);
 
 	dwc3_gadget_free_endpoints(dwc);
-- 
1.9.1


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

* [RFC 14/19] dwc3: host: don't add XHCI device only if in OTG mode
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (12 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 13/19] dwc3: gadget: register gadget in OTG core Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 15/19] dwc3: core: initialize OTG in DWC3 core Robert Baldyga
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This patch causes that XHCI device is not added automatically in
dwc3_host_init() if we run in OTG mode. OTG handling code registers
XHCI device when USB host cable is detected.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/host.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index c679f63..4b07f13 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -62,10 +62,12 @@ int dwc3_host_init(struct dwc3 *dwc)
 	phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy",
 			  dev_name(&xhci->dev));
 
-	ret = platform_device_add(xhci);
-	if (ret) {
-		dev_err(dwc->dev, "failed to register xHCI device\n");
-		goto err2;
+	if (!dwc->dotg) {
+		ret = platform_device_add(xhci);
+		if (ret) {
+			dev_err(dwc->dev, "failed to register xHCI device\n");
+			goto err2;
+		}
 	}
 
 	return 0;
-- 
1.9.1


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

* [RFC 15/19] dwc3: core: initialize OTG in DWC3 core
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (13 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 14/19] dwc3: host: don't add XHCI device only if in OTG mode Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 16/19] dwc3: exynos: add software role switching code Robert Baldyga
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

This patch adds OTG initialization in DWC3 core. This finally enables
OTG feature if selected operation mode is "otg". It also initializes
and deinitialized OTG in suspend/resume functions.

After this changes DWC3 core is uninitialized by default in OTG mode.
The dwc3_core_init() function is called after relevant cable detection.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/dwc3/core.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index d519b31..e5af049 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -43,6 +43,7 @@
 #include "platform_data.h"
 #include "core.h"
 #include "gadget.h"
+#include "otg.h"
 #include "io.h"
 
 #include "debug.h"
@@ -687,17 +688,37 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
 		break;
 	case USB_DR_MODE_OTG:
 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
+		ret = dwc3_otg_init(dwc);
+		if (ret) {
+			dev_err(dev, "failed to initialize otg\n");
+			return ret;
+		}
+
 		ret = dwc3_host_init(dwc);
 		if (ret) {
 			dev_err(dev, "failed to initialize host\n");
+			dwc3_otg_exit(dwc);
 			return ret;
 		}
 
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
 			dev_err(dev, "failed to initialize gadget\n");
+			dwc3_host_exit(dwc);
+			dwc3_otg_exit(dwc);
 			return ret;
 		}
+
+		/* Now we are ready to start OTG */
+		ret = dwc3_otg_start(dwc);
+		if (ret) {
+			dev_err(dev, "failed to start otg\n");
+			dwc3_host_exit(dwc);
+			dwc3_gadget_exit(dwc);
+			dwc3_otg_exit(dwc);
+			return ret;
+		}
+
 		break;
 	default:
 		dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
@@ -717,8 +738,10 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
 		dwc3_host_exit(dwc);
 		break;
 	case USB_DR_MODE_OTG:
+		dwc3_otg_stop(dwc);
 		dwc3_host_exit(dwc);
 		dwc3_gadget_exit(dwc);
+		dwc3_otg_exit(dwc);
 		break;
 	default:
 		/* do nothing */
@@ -932,6 +955,12 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err3;
 
+	if (dwc->dotg) {
+		dwc3_core_exit(dwc);
+		dwc->needs_reinit = 1;
+		pm_runtime_put_sync(dev);
+	}
+
 	ret = dwc3_core_init_mode(dwc);
 	if (ret)
 		goto err4;
@@ -1009,6 +1038,9 @@ static int dwc3_suspend(struct device *dev)
 	struct dwc3	*dwc = dev_get_drvdata(dev);
 	unsigned long	flags;
 
+	if (dwc->dotg)
+		dwc3_otg_stop(dwc);
+
 	spin_lock_irqsave(&dwc->lock, flags);
 
 	switch (dwc->dr_mode) {
@@ -1067,6 +1099,9 @@ static int dwc3_resume(struct device *dev)
 	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
 
+	if (dwc->dotg)
+		dwc3_otg_start(dwc);
+
 	return 0;
 
 err_usb2phy_init:
-- 
1.9.1


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

* [RFC 16/19] dwc3: exynos: add software role switching code
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (14 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 15/19] dwc3: core: initialize OTG in DWC3 core Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 17/19] ARM: dts: exynos5420: set usb3_lpm_capable in dwc3 controllers Robert Baldyga
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Exynos platform doesn't have hardware OTG support in DWC3 block, so we
need to supply custom mechanism of notification about cable change. For
this purpose we use extcon framework - it would allow to use this code
with each Exynos board equipped with cable detecting hardware which has
its extcon driver.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 .../devicetree/bindings/usb/exynos-usb.txt         |   4 +
 drivers/usb/dwc3/dwc3-exynos.c                     | 162 +++++++++++++++++++++
 drivers/usb/dwc3/otg.c                             |  25 ++++
 drivers/usb/dwc3/otg.h                             |   9 ++
 4 files changed, 200 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt
index 9b4dbe3..34b049f 100644
--- a/Documentation/devicetree/bindings/usb/exynos-usb.txt
+++ b/Documentation/devicetree/bindings/usb/exynos-usb.txt
@@ -93,6 +93,10 @@ Required properties:
  - clocks: Clock IDs array as required by the controller.
  - clock-names: names of clocks correseponding to IDs in the clock property
 
+Optional properties:
+ - extcon: Phandle to extcon device which notifies about USB cable changes.
+	   It's used in OTG mode.
+
 Sub-nodes:
 The dwc3 core should be added as subnode to Exynos dwc3 glue.
 - dwc3 :
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 7bd0a95..30a0560 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -27,6 +27,10 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/regulator/consumer.h>
+#include <linux/extcon.h>
+#include <linux/workqueue.h>
+
+#include "otg.h"
 
 struct dwc3_exynos {
 	struct platform_device	*usb2_phy;
@@ -39,8 +43,107 @@ struct dwc3_exynos {
 
 	struct regulator	*vdd33;
 	struct regulator	*vdd10;
+
+	struct otg_fsm          *fsm;
+
+	struct extcon_dev       *extcon;
+	struct extcon_specific_cable_nb extcon_usb_dev;
+	struct extcon_specific_cable_nb extcon_usb_host_dev;
+	struct notifier_block   usb_nb;
+	struct notifier_block   usb_host_nb;
+	struct work_struct	work;
 };
 
+static int dwc3_exynos_usb_notifier(struct notifier_block *nb,
+		unsigned long event, void *ptr);
+
+static int dwc3_exynos_usb_host_notifier(struct notifier_block *nb,
+		unsigned long event, void *ptr);
+
+int dwc3_exynos_rsw_start(struct device *dev)
+{
+	struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (!exynos->extcon)
+		return -ENODEV;
+
+	exynos->usb_nb.notifier_call = dwc3_exynos_usb_notifier;
+	exynos->usb_host_nb.notifier_call = dwc3_exynos_usb_host_notifier;
+
+	ret = extcon_register_interest(&exynos->extcon_usb_dev,
+			exynos->extcon->name, "USB", &exynos->usb_nb);
+	if (ret < 0) {
+		dev_dbg(dev, "failed to register notifier for USB");
+		return -ENODEV;
+	}
+
+	ret = extcon_register_interest(&exynos->extcon_usb_host_dev,
+			exynos->extcon->name, "USB-HOST", &exynos->usb_host_nb);
+	if (ret < 0) {
+		dev_dbg(dev, "failed to register notifier for USB HOST");
+		extcon_unregister_interest(&exynos->extcon_usb_dev);
+		return -ENODEV;
+	}
+
+	if (extcon_get_cable_state(exynos->extcon, "USB")) {
+		exynos->fsm->b_sess_vld = 1;
+		exynos->fsm->id = 1;
+	} else if (extcon_get_cable_state(exynos->extcon, "USB-HOST")) {
+		exynos->fsm->b_sess_vld = 0;
+		exynos->fsm->id = 0;
+	} else {
+		exynos->fsm->b_sess_vld = 0;
+		exynos->fsm->id = 1;
+	}
+
+	dwc3_otg_run_sm(exynos->fsm);
+
+	return 0;
+}
+
+void dwc3_exynos_rsw_stop(struct device *dev)
+{
+	struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (exynos->extcon_usb_dev.edev)
+		extcon_unregister_interest(&exynos->extcon_usb_dev);
+	if (exynos->extcon_usb_host_dev.edev)
+		extcon_unregister_interest(&exynos->extcon_usb_host_dev);
+}
+
+int dwc3_exynos_rsw_setup(struct device *dev, struct otg_fsm *fsm)
+{
+	struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	exynos->fsm = fsm;
+
+	return 0;
+}
+
+void dwc3_exynos_rsw_exit(struct device *dev)
+{
+	struct dwc3_exynos	*exynos = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	exynos->fsm = NULL;
+}
+
+bool dwc3_exynos_rsw_available(struct device *dev)
+{
+	if (of_property_read_bool(dev->of_node, "extcon"))
+		return true;
+
+	return false;
+}
+
 static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
 {
 	struct usb_phy_generic_platform_data pdata;
@@ -105,18 +208,77 @@ static int dwc3_exynos_remove_child(struct device *dev, void *unused)
 	return 0;
 }
 
+static void dwc3_exynos_worker(struct work_struct *work)
+{
+	struct dwc3_exynos *exynos =
+		container_of(work, struct dwc3_exynos, work);
+
+	dwc3_otg_run_sm(exynos->fsm);
+}
+
+static int dwc3_exynos_usb_notifier(struct notifier_block *nb,
+		unsigned long event, void *ptr)
+{
+	struct dwc3_exynos *exynos =
+		container_of(nb, struct dwc3_exynos, usb_nb);
+
+	if (event) {
+		exynos->fsm->b_sess_vld = 1;
+		exynos->fsm->id = 1;
+	} else {
+		exynos->fsm->b_sess_vld = 0;
+		exynos->fsm->id = 1;
+	}
+
+	schedule_work(&exynos->work);
+
+	return 0;
+}
+
+static int dwc3_exynos_usb_host_notifier(struct notifier_block *nb,
+		unsigned long event, void *ptr)
+{
+	struct dwc3_exynos *exynos =
+		container_of(nb, struct dwc3_exynos, usb_host_nb);
+
+	if (event) {
+		exynos->fsm->b_sess_vld = 0;
+		exynos->fsm->id = 0;
+	} else {
+		exynos->fsm->b_sess_vld = 0;
+		exynos->fsm->id = 1;
+	}
+
+	schedule_work(&exynos->work);
+
+	return 0;
+}
+
 static int dwc3_exynos_probe(struct platform_device *pdev)
 {
 	struct dwc3_exynos	*exynos;
 	struct device		*dev = &pdev->dev;
 	struct device_node	*node = dev->of_node;
+	struct extcon_dev       *extcon = NULL;
 
 	int			ret;
 
+	if (of_property_read_bool(node, "extcon")) {
+		extcon = extcon_get_edev_by_phandle(dev, 0);
+		if (IS_ERR(extcon)) {
+			dev_vdbg(dev, "couldn't get extcon device\n");
+			return -EPROBE_DEFER;
+		}
+	}
+
 	exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
 	if (!exynos)
 		return -ENOMEM;
 
+	exynos->extcon = extcon;
+
+	INIT_WORK(&exynos->work, dwc3_exynos_worker);
+
 	/*
 	 * Right now device-tree probed devices don't get dma_mask set.
 	 * Since shared usb code relies on it, set it here for now.
diff --git a/drivers/usb/dwc3/otg.c b/drivers/usb/dwc3/otg.c
index 99dfd2c..507bade 100644
--- a/drivers/usb/dwc3/otg.c
+++ b/drivers/usb/dwc3/otg.c
@@ -29,10 +29,35 @@
 #include "otg.h"
 #include "io.h"
 
+#if IS_ENABLED(CONFIG_USB_DWC3_EXYNOS)
+static struct dwc3_ext_otg_ops *dwc3_otg_rsw_probe(struct dwc3 *dwc)
+{
+	struct dwc3_ext_otg_ops *ops;
+	bool                    ext_otg;
+
+	ext_otg = dwc3_exynos_rsw_available(dwc->dev->parent);
+	if (!ext_otg)
+		return NULL;
+
+	/* Allocate and init otg instance */
+	ops = devm_kzalloc(dwc->dev, sizeof(struct dwc3_ext_otg_ops),
+			GFP_KERNEL);
+	if (!ops)
+		return NULL;
+
+	ops->setup = dwc3_exynos_rsw_setup;
+	ops->exit = dwc3_exynos_rsw_exit;
+	ops->start = dwc3_exynos_rsw_start;
+	ops->stop = dwc3_exynos_rsw_stop;
+
+	return ops;
+}
+#else
 static struct dwc3_ext_otg_ops *dwc3_otg_rsw_probe(struct dwc3 *dwc)
 {
 	return NULL;
 }
+#endif
 
 static void dwc3_otg_set_host_mode(struct dwc3_otg *dotg)
 {
diff --git a/drivers/usb/dwc3/otg.h b/drivers/usb/dwc3/otg.h
index 4be7165..efed700 100644
--- a/drivers/usb/dwc3/otg.h
+++ b/drivers/usb/dwc3/otg.h
@@ -101,4 +101,13 @@ void dwc3_otg_exit(struct dwc3 *dwc);
 
 void dwc3_otg_run_sm(struct otg_fsm *fsm);
 
+/* prototypes */
+#if IS_ENABLED(CONFIG_USB_DWC3_EXYNOS)
+bool dwc3_exynos_rsw_available(struct device *dev);
+int dwc3_exynos_rsw_setup(struct device *dev, struct otg_fsm *fsm);
+void dwc3_exynos_rsw_exit(struct device *dev);
+int dwc3_exynos_rsw_start(struct device *dev);
+void dwc3_exynos_rsw_stop(struct device *dev);
+#endif
+
 #endif /* __LINUX_USB_DWC3_OTG_H */
-- 
1.9.1


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

* [RFC 17/19] ARM: dts: exynos5420: set usb3_lpm_capable in dwc3 controllers
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (15 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 16/19] dwc3: exynos: add software role switching code Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 18/19] ARM: dts: exynos5420: add snps,dis_u3_susphy_quirk to " Robert Baldyga
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

These hardware has LPM and we want to use it. This change fixes
problem with VBUS power on after switching to host mode.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 arch/arm/boot/dts/exynos5420.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 9dc2e97..d4b50ea 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -847,6 +847,7 @@
 			interrupts = <0 72 0>;
 			phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
 			phy-names = "usb2-phy", "usb3-phy";
+			snps,usb3_lpm_capable;
 		};
 	};
 
@@ -873,6 +874,7 @@
 			interrupts = <0 73 0>;
 			phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
 			phy-names = "usb2-phy", "usb3-phy";
+			snps,usb3_lpm_capable;
 		};
 	};
 
-- 
1.9.1


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

* [RFC 18/19] ARM: dts: exynos5420: add snps,dis_u3_susphy_quirk to dwc3 controllers
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (16 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 17/19] ARM: dts: exynos5420: set usb3_lpm_capable in dwc3 controllers Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-18 14:04 ` [RFC 19/19] ARM: dts: exynos5422-odroidxu3: make usbdrd3 extcon client Robert Baldyga
  2015-03-19  2:33 ` [RFC 00/19] dwc3: add USB OTG role switch support Chanwoo Choi
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

It's needed for proper role switching in OTG mode. Without this change
ep0 fails to be enabled after switching to gadget mode.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 arch/arm/boot/dts/exynos5420.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index d4b50ea..7604ccf 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -848,6 +848,8 @@
 			phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
 			phy-names = "usb2-phy", "usb3-phy";
 			snps,usb3_lpm_capable;
+			snps,dis_u3_susphy_quirk;
+			snps,dis_u2_susphy_quirk;
 		};
 	};
 
@@ -875,6 +877,8 @@
 			phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
 			phy-names = "usb2-phy", "usb3-phy";
 			snps,usb3_lpm_capable;
+			snps,dis_u3_susphy_quirk;
+			snps,dis_u2_susphy_quirk;
 		};
 	};
 
-- 
1.9.1


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

* [RFC 19/19] ARM: dts: exynos5422-odroidxu3: make usbdrd3 extcon client
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (17 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 18/19] ARM: dts: exynos5420: add snps,dis_u3_susphy_quirk to " Robert Baldyga
@ 2015-03-18 14:04 ` Robert Baldyga
  2015-03-19  2:33 ` [RFC 00/19] dwc3: add USB OTG role switch support Chanwoo Choi
  19 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-18 14:04 UTC (permalink / raw)
  To: balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Robert Baldyga

Make usbdrd3 an extcon client to enable OTG role switching feature.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 arch/arm/boot/dts/exynos5422-odroidxu3.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index 80057d6..ec8eed3 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -338,6 +338,10 @@
 	};
 };
 
+&usbdrd3_1 {
+	extcon = <&usb_extcon>;
+};
+
 &usbdrd_dwc3_0 {
 	dr_mode = "host";
 };
-- 
1.9.1


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

* Re: [RFC 07/19] dwc3: core: cleanup suspend/resume code
  2015-03-18 14:04 ` [RFC 07/19] dwc3: core: cleanup suspend/resume code Robert Baldyga
@ 2015-03-18 15:00   ` Sergei Shtylyov
  0 siblings, 0 replies; 32+ messages in thread
From: Sergei Shtylyov @ 2015-03-18 15:00 UTC (permalink / raw)
  To: Robert Baldyga, balbi
  Cc: gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel, m.szyprowski

Hello.

On 3/18/2015 5:04 PM, Robert Baldyga wrote:

> Remove unused cases from switch-case statement and place
> dwc3_event_buffers_cleanup() function outside switch-case
> as it's called in each case anyway.

> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
>   drivers/usb/dwc3/core.c | 8 ++------
>   1 file changed, 2 insertions(+), 6 deletions(-)

> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 2bbab3d..b040ce0 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -1018,13 +1018,12 @@ static int dwc3_suspend(struct device *dev)
>   	case USB_DR_MODE_PERIPHERAL:
>   	case USB_DR_MODE_OTG:
>   		dwc3_gadget_suspend(dwc);
> -		/* FALLTHROUGH */

    Why are you removing comment that stays valid?

> -	case USB_DR_MODE_HOST:
>   	default:
> -		dwc3_event_buffers_cleanup(dwc);
>   		break;
>   	}
>
> +	dwc3_event_buffers_cleanup(dwc);
> +
>   	dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
>   	spin_unlock_irqrestore(&dwc->lock, flags);
>
> @@ -1061,10 +1060,7 @@ static int dwc3_resume(struct device *dev)
>   	case USB_DR_MODE_PERIPHERAL:
>   	case USB_DR_MODE_OTG:
>   		dwc3_gadget_resume(dwc);
> -		/* FALLTHROUGH */

    Likewise.

> -	case USB_DR_MODE_HOST:
>   	default:
> -		/* do nothing */
>   		break;
>   	}
>

WBR, Sergei


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

* Re: [RFC 00/19] dwc3: add USB OTG role switch support
  2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
                   ` (18 preceding siblings ...)
  2015-03-18 14:04 ` [RFC 19/19] ARM: dts: exynos5422-odroidxu3: make usbdrd3 extcon client Robert Baldyga
@ 2015-03-19  2:33 ` Chanwoo Choi
  2015-03-19  8:27   ` Robert Baldyga
  19 siblings, 1 reply; 32+ messages in thread
From: Chanwoo Choi @ 2015-03-19  2:33 UTC (permalink / raw)
  To: Robert Baldyga
  Cc: balbi, gregkh, myungjoo.ham, linux-usb, linux-kernel, m.szyprowski

Hi Robert,

Did you test the extcon-odroid-otg driver on Odroid-U3?

Thanks,
Chanwoo Choi

On 03/18/2015 11:04 PM, Robert Baldyga wrote:
> Hello,
> 
> This patchset introduces OTG feature in DWC3 DRD driver. This allows
> to change dynamically between host and peripheral mode depending on
> detected USB cable type.
> 
> DWC3 driver behaviour is changed only in situation when selected operation
> mode (dr_mode) is "otg", and hardware OTG support is available or extended
> OTG operations are supplied for given platform.
> 
> It such conditions are fulfilled, none of modes is enabled by default
> and dwc3 core Best regards,
> Robert Baldygais being uninitialized. After USB cable detection relevant
> mode is selected and dwc3 core is initialized. Cable disconnection causes
> deinitialization of dwc3 core.
> 
> File otg.c is inspired by code of DWC3 driver from Hardkernel linux
> sources [1]. I have never tested it on DWC3 version equipped with hardware
> OTG support, but I belive that this code have chance to work or at least
> it's easy to fix. I have tested this on OdroidXU3 board which has USB
> cable detection mechanism based on two gpio pins. I used extcon driver
> for those feature, which is also attached to following patchset.
> 
> I consider if ext_otg_ops it the right solution. Current solution is
> based on Hardkernel sources, but it's very likely that adding extcon
> support directly to otg.c would be generic enough, as most of cable
> detection mechanisms can be simply represented by extcon devices.
> 
> Thanks in advance for your comments.
> 
> Best regards,
> Robert Baldyga
> 
> [1] https://github.com/hardkernel/linux
> 
> Robert Baldyga (19):
>   extcon: add extcon-odroid-usbotg driver
>   dt-bindings: extcon: Add doc for extcon-odroid-usbotg
>   ARM: dts: exynos5422-odroidxu3: add odroid-usbotg extcon support
>   dwc3: gadget: add VBUS session handling
>   dwc3: gadget: enable/disable ep0 in dwc3_gadget_run_stop()
>   dwc3: gadget: check returned value in suspend/resume
>   dwc3: core: cleanup suspend/resume code
>   dwc3: core: handle event buffers in core_init/exit
>   dwc3: core: make dwc3_core_init/exit non-static
>   dwc3: add missing OTG register definitions
>   dwc3: add OTG handling code
>   dwc3: otg: add ext_otg_ops support
>   dwc3: gadget: register gadget in OTG core
>   dwc3: host: don't add XHCI device only if in OTG mode
>   dwc3: core: initialize OTG in DWC3 core
>   dwc3: exynos: add software role switching code
>   ARM: dts: exynos5420: set usb3_lpm_capable in dwc3 controllers
>   ARM: dts: exynos5420: add snps,dis_u3_susphy_quirk to dwc3 controllers
>   ARM: dts: exynos5422-odroidxu3: make usbdrd3 extcon client
> 
>  .../bindings/extcon/extcon-odroid-usbotg.txt       |  16 +
>  .../devicetree/bindings/usb/exynos-usb.txt         |   4 +
>  arch/arm/boot/dts/exynos5420.dtsi                  |   6 +
>  arch/arm/boot/dts/exynos5422-odroidxu3.dts         |  24 +
>  drivers/extcon/Kconfig                             |   4 +
>  drivers/extcon/Makefile                            |   1 +
>  drivers/extcon/extcon-odroid-usbotg.c              | 257 +++++++++
>  drivers/usb/dwc3/Kconfig                           |   1 +
>  drivers/usb/dwc3/Makefile                          |   4 +
>  drivers/usb/dwc3/core.c                            |  66 ++-
>  drivers/usb/dwc3/core.h                            |  22 +
>  drivers/usb/dwc3/dwc3-exynos.c                     | 162 ++++++
>  drivers/usb/dwc3/gadget.c                          | 106 ++--
>  drivers/usb/dwc3/host.c                            |  10 +-
>  drivers/usb/dwc3/otg.c                             | 577 +++++++++++++++++++++
>  drivers/usb/dwc3/otg.h                             | 113 ++++
>  16 files changed, 1320 insertions(+), 53 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/extcon/extcon-odroid-usbotg.txt
>  create mode 100644 drivers/extcon/extcon-odroid-usbotg.c
>  create mode 100644 drivers/usb/dwc3/otg.c
>  create mode 100644 drivers/usb/dwc3/otg.h
> 


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

* Re: [RFC 11/19] dwc3: add OTG handling code
  2015-03-18 14:04 ` [RFC 11/19] dwc3: add OTG handling code Robert Baldyga
@ 2015-03-19  7:38   ` George Cherian
  0 siblings, 0 replies; 32+ messages in thread
From: George Cherian @ 2015-03-19  7:38 UTC (permalink / raw)
  To: Robert Baldyga
  Cc: balbi, gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski

Hi Robert,


On Wed, Mar 18, 2015 at 7:34 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>
> This patch introduces OTG support in DWC3 driver. OTG feature is responsible
> for dynamic USB role switching (between host and peripheral modes) based
> on detected cable type.
>
> Each role switch causes complete core reinitialization. In peripheral

Do you really want to do complete core reinitialization?
While switching to HOST mode you might need to issue a LHRESET and
while switching
to Device mode make sure you re-initiallize the event buffer addresses.

If LHRESET is not used then you should do what you have done.

But I don't think adding and removing the platform_device for XHCI is
the way to go.
This might impact SoC's which really implement the OTG for DWC3.

I made an attempt on the same  and could'nt work on it more.
This still has some issues, but could be fixed.
https://lkml.org/lkml/2014/11/25/600

> mode UDC device is activated using VBUS session control mechanism. In
> host mode the new XHCI device is registered to make bus visible in system.
>
> This code is inspired by DWC3 driver from Hardkernel Linux sources [1].
>
> [1] https://github.com/hardkernel/linux.
>
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>

Regards
-George

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

* Re: [RFC 00/19] dwc3: add USB OTG role switch support
  2015-03-19  2:33 ` [RFC 00/19] dwc3: add USB OTG role switch support Chanwoo Choi
@ 2015-03-19  8:27   ` Robert Baldyga
  0 siblings, 0 replies; 32+ messages in thread
From: Robert Baldyga @ 2015-03-19  8:27 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: balbi, gregkh, myungjoo.ham, linux-usb, linux-kernel, m.szyprowski

Hi Chanwoo,

On 03/19/2015 03:33 AM, Chanwoo Choi wrote:
> Hi Robert,
> 
> Did you test the extcon-odroid-otg driver on Odroid-U3?

Yes, I tested it with Odroid U3, U3+, X2, XU3 and it works well.

Best regards,
Robert

> 
> Thanks,
> Chanwoo Choi
> 
> On 03/18/2015 11:04 PM, Robert Baldyga wrote:
>> Hello,
>>
>> This patchset introduces OTG feature in DWC3 DRD driver. This allows
>> to change dynamically between host and peripheral mode depending on
>> detected USB cable type.
>>
>> DWC3 driver behaviour is changed only in situation when selected operation
>> mode (dr_mode) is "otg", and hardware OTG support is available or extended
>> OTG operations are supplied for given platform.
>>
>> It such conditions are fulfilled, none of modes is enabled by default
>> and dwc3 core Best regards,
>> Robert Baldygais being uninitialized. After USB cable detection relevant
>> mode is selected and dwc3 core is initialized. Cable disconnection causes
>> deinitialization of dwc3 core.
>>
>> File otg.c is inspired by code of DWC3 driver from Hardkernel linux
>> sources [1]. I have never tested it on DWC3 version equipped with hardware
>> OTG support, but I belive that this code have chance to work or at least
>> it's easy to fix. I have tested this on OdroidXU3 board which has USB
>> cable detection mechanism based on two gpio pins. I used extcon driver
>> for those feature, which is also attached to following patchset.
>>
>> I consider if ext_otg_ops it the right solution. Current solution is
>> based on Hardkernel sources, but it's very likely that adding extcon
>> support directly to otg.c would be generic enough, as most of cable
>> detection mechanisms can be simply represented by extcon devices.
>>
>> Thanks in advance for your comments.
>>
>> Best regards,
>> Robert Baldyga
>>
>> [1] https://github.com/hardkernel/linux
>>
>> Robert Baldyga (19):
>>   extcon: add extcon-odroid-usbotg driver
>>   dt-bindings: extcon: Add doc for extcon-odroid-usbotg
>>   ARM: dts: exynos5422-odroidxu3: add odroid-usbotg extcon support
>>   dwc3: gadget: add VBUS session handling
>>   dwc3: gadget: enable/disable ep0 in dwc3_gadget_run_stop()
>>   dwc3: gadget: check returned value in suspend/resume
>>   dwc3: core: cleanup suspend/resume code
>>   dwc3: core: handle event buffers in core_init/exit
>>   dwc3: core: make dwc3_core_init/exit non-static
>>   dwc3: add missing OTG register definitions
>>   dwc3: add OTG handling code
>>   dwc3: otg: add ext_otg_ops support
>>   dwc3: gadget: register gadget in OTG core
>>   dwc3: host: don't add XHCI device only if in OTG mode
>>   dwc3: core: initialize OTG in DWC3 core
>>   dwc3: exynos: add software role switching code
>>   ARM: dts: exynos5420: set usb3_lpm_capable in dwc3 controllers
>>   ARM: dts: exynos5420: add snps,dis_u3_susphy_quirk to dwc3 controllers
>>   ARM: dts: exynos5422-odroidxu3: make usbdrd3 extcon client
>>
>>  .../bindings/extcon/extcon-odroid-usbotg.txt       |  16 +
>>  .../devicetree/bindings/usb/exynos-usb.txt         |   4 +
>>  arch/arm/boot/dts/exynos5420.dtsi                  |   6 +
>>  arch/arm/boot/dts/exynos5422-odroidxu3.dts         |  24 +
>>  drivers/extcon/Kconfig                             |   4 +
>>  drivers/extcon/Makefile                            |   1 +
>>  drivers/extcon/extcon-odroid-usbotg.c              | 257 +++++++++
>>  drivers/usb/dwc3/Kconfig                           |   1 +
>>  drivers/usb/dwc3/Makefile                          |   4 +
>>  drivers/usb/dwc3/core.c                            |  66 ++-
>>  drivers/usb/dwc3/core.h                            |  22 +
>>  drivers/usb/dwc3/dwc3-exynos.c                     | 162 ++++++
>>  drivers/usb/dwc3/gadget.c                          | 106 ++--
>>  drivers/usb/dwc3/host.c                            |  10 +-
>>  drivers/usb/dwc3/otg.c                             | 577 +++++++++++++++++++++
>>  drivers/usb/dwc3/otg.h                             | 113 ++++
>>  16 files changed, 1320 insertions(+), 53 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/extcon/extcon-odroid-usbotg.txt
>>  create mode 100644 drivers/extcon/extcon-odroid-usbotg.c
>>  create mode 100644 drivers/usb/dwc3/otg.c
>>  create mode 100644 drivers/usb/dwc3/otg.h
>>
> 
> 


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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-18 14:04 ` [RFC 01/19] extcon: add extcon-odroid-usbotg driver Robert Baldyga
@ 2015-03-19  8:50   ` George Cherian
  2015-03-19 12:07     ` Robert Baldyga
  0 siblings, 1 reply; 32+ messages in thread
From: George Cherian @ 2015-03-19  8:50 UTC (permalink / raw)
  To: Robert Baldyga
  Cc: balbi, gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Łukasz Stelmach

Hi Robert,

This looks like a extcon driver based on gpio for USB.

Roger posted a generic one a while back.
https://lkml.org/lkml/2015/2/2/187

Doesn't this serve the purpose rather than adding this driver?

-George

On Wed, Mar 18, 2015 at 7:34 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
> This patch adds extcon driver for Odroid U3, U3+ and X boards.
> It recognizes type of USB cable connected to Odroid board basing on
> two signal lines VBUS_DET and OTG_ID (the second one is present only
> on Odroid U3+ board).
>
> Following table of states presents relationship between this signals
> and detected cable type:
>
> state    | VBUS_DET |  OTG_ID
> -------------------------------
> USB      |    H     |    H
> USB_HOST |    H     |    L
> disconn. |    L     |    H
> USB-HOST |    L     |    L
>
> This driver is based on extcon-gpio driver.
>
> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
>  drivers/extcon/Kconfig                |   4 +
>  drivers/extcon/Makefile               |   1 +
>  drivers/extcon/extcon-odroid-usbotg.c | 256 ++++++++++++++++++++++++++++++++++
>  3 files changed, 261 insertions(+)
>  create mode 100644 drivers/extcon/extcon-odroid-usbotg.c
>
> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
> index 6a1f7de..891dca3 100644
> --- a/drivers/extcon/Kconfig
> +++ b/drivers/extcon/Kconfig
> @@ -93,4 +93,8 @@ config EXTCON_SM5502
>           Silicon Mitus SM5502. The SM5502 is a USB port accessory
>           detector and switch.
>
> +config EXTCON_ODROID_USBOTG
> +       tristate "Extcon Odroid U3, U3+, X and XU USB OTG port"
> +       depends on OF_GPIO
> +
>  endif # MULTISTATE_SWITCH
> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
> index 0370b42..514384e 100644
> --- a/drivers/extcon/Makefile
> +++ b/drivers/extcon/Makefile
> @@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997)  += extcon-max8997.o
>  obj-$(CONFIG_EXTCON_PALMAS)    += extcon-palmas.o
>  obj-$(CONFIG_EXTCON_RT8973A)   += extcon-rt8973a.o
>  obj-$(CONFIG_EXTCON_SM5502)    += extcon-sm5502.o
> +obj-$(CONFIG_EXTCON_ODROID_USBOTG) += extcon-odroid-usbotg.o
> diff --git a/drivers/extcon/extcon-odroid-usbotg.c b/drivers/extcon/extcon-odroid-usbotg.c
> new file mode 100644
> index 0000000..7f71c48
> --- /dev/null
> +++ b/drivers/extcon/extcon-odroid-usbotg.c
> @@ -0,0 +1,256 @@
> +/*
> + *  drivers/extcon/extcon-odroid-usbotg.c
> + *
> + *  USB cable extcon driver for Odroid U3, Odroid U3+ and Odroid X
> + *
> + * Copyright (C) 2014 Samsung Electronics
> + * Author: Lukasz Stelmach <l.stelmach@samsung.com>
> + * Author: Robert Baldyga <r.baldyga@samsung.com>
> + *
> + * based on drivers/extcon/extcon-gpio.c
> + * Copyright (C) 2008 Google, Inc.
> + * Author: Mike Lockwood <lockwood@android.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <linux/extcon.h>
> +#include <linux/extcon/extcon-gpio.h>
> +#include <linux/delay.h>
> +
> +enum {
> +       EXTCON_CABLE_USB = 0,
> +       EXTCON_CABLE_USB_HOST,
> +
> +       _EXTCON_CABLE_NUM,
> +};
> +
> +static const char * const odroid_usbotg_cable[] = {
> +       [EXTCON_CABLE_USB] = "USB",
> +       [EXTCON_CABLE_USB_HOST] = "USB-HOST",
> +
> +       NULL,
> +};
> +
> +struct odroid_usbotg_data {
> +       struct extcon_dev *edev;
> +       struct gpio_desc *otg_id;
> +       struct gpio_desc *vbus_det;
> +       int otg_id_irq;
> +       int vbus_det_irq;
> +       unsigned long debounce_ms;
> +};
> +
> +/*
> + * state    | VBUS_DET |  OTG_ID
> + * -------------------------------
> + * USB      |    H     |    H
> + * USB-HOST |    H     |    L
> + * disconn. |    L     |    H
> + * USB-HOST |    L     |    L
> + *
> + * Only Odroid U3+ has OTG_ID line. U3 and X versions can detect only
> + * USB slave cable.
> + */
> +
> +static void odroid_usbotg_detect_cable(struct odroid_usbotg_data *extcon_data)
> +{
> +       int state;
> +
> +       mdelay(extcon_data->debounce_ms);
> +
> +       if (extcon_data->otg_id)
> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) |
> +                       gpiod_get_value(extcon_data->otg_id);
> +       else
> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) | 1;
> +
> +       dev_dbg(&extcon_data->edev->dev, "cable state changed to %d\n", state);
> +
> +       if (state & 0x1)
> +               extcon_set_cable_state_(extcon_data->edev,
> +                       EXTCON_CABLE_USB_HOST, false);
> +       if (state != 0x3)
> +               extcon_set_cable_state_(extcon_data->edev,
> +                       EXTCON_CABLE_USB, false);
> +
> +       if (!(state & 0x1))
> +               extcon_set_cable_state_(extcon_data->edev,
> +                       EXTCON_CABLE_USB_HOST, true);
> +       else if (state == 0x3)
> +               extcon_set_cable_state_(extcon_data->edev,
> +                       EXTCON_CABLE_USB, true);
> +}
> +
> +static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
> +{
> +       struct odroid_usbotg_data *extcon_data = dev_id;
> +
> +       odroid_usbotg_detect_cable(extcon_data);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int odroid_usbotg_parse_dt(struct platform_device *pdev,
> +                                   struct odroid_usbotg_data *extcon_data)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       u32 val;
> +
> +       if (!np)
> +               return -ENODEV;
> +
> +       extcon_data->edev->name = np->name;
> +
> +       if (of_property_read_u32(np, "debounce", &val) != 0)
> +               val = 50;
> +       extcon_data->debounce_ms = val;
> +
> +       return 0;
> +}
> +
> +static int odroid_usbotg_probe(struct platform_device *pdev)
> +{
> +       struct odroid_usbotg_data *extcon_data;
> +       int ret = 0;
> +
> +       extcon_data = devm_kzalloc(&pdev->dev,
> +               sizeof(struct odroid_usbotg_data), GFP_KERNEL);
> +       if (!extcon_data)
> +               return -ENOMEM;
> +
> +       extcon_data->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
> +                                        GFP_KERNEL);
> +       if (IS_ERR(extcon_data->edev)) {
> +               dev_err(&pdev->dev, "failed to allocate extcon device\n");
> +               return -ENOMEM;
> +       }
> +       extcon_data->edev->supported_cable = odroid_usbotg_cable;
> +
> +       ret = odroid_usbotg_parse_dt(pdev, extcon_data);
> +       if (IS_ERR_VALUE(ret)) {
> +               dev_err(&pdev->dev, "failed to get data from device tree\n");
> +               return ret;
> +       }
> +
> +       /* gpios */
> +       extcon_data->vbus_det = devm_gpiod_get(&pdev->dev, "vbus-det");
> +       if (IS_ERR(extcon_data->vbus_det)) {
> +               dev_err(&pdev->dev, "failed to get vbus_det gpio\n");
> +               return PTR_ERR(extcon_data->vbus_det);
> +       }
> +       extcon_data->otg_id = devm_gpiod_get_optional(&pdev->dev, "otg-id");
> +
> +       extcon_data->edev->dev.parent = &pdev->dev;
> +       ret = extcon_dev_register(extcon_data->edev);
> +       if (ret < 0)
> +               return ret;
> +
> +       /* irq */
> +       extcon_data->vbus_det_irq = gpiod_to_irq(extcon_data->vbus_det);
> +       if (extcon_data->vbus_det_irq < 0) {
> +               dev_err(&pdev->dev, "failed to get irq from vbus_det\n");
> +               ret = extcon_data->vbus_det_irq;
> +               goto err;
> +       }
> +       ret = request_threaded_irq(extcon_data->vbus_det_irq, NULL,
> +                                  gpio_irq_handler, IRQF_ONESHOT |
> +                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
> +                                  pdev->name, extcon_data);
> +       if (ret < 0) {
> +               dev_err(&pdev->dev, "failed to request vbus_det irq\n");
> +               goto err;
> +       }
> +
> +       if (extcon_data->otg_id) {
> +               extcon_data->otg_id_irq = gpiod_to_irq(extcon_data->otg_id);
> +               if (extcon_data->otg_id_irq < 0) {
> +                       dev_err(&pdev->dev, "failed to get irq from otg_id\n");
> +                       ret = extcon_data->otg_id_irq;
> +                       goto err;
> +               }
> +               ret = request_threaded_irq(extcon_data->otg_id_irq, NULL,
> +                               gpio_irq_handler, IRQF_ONESHOT |
> +                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
> +                               pdev->name, extcon_data);
> +               if (ret < 0) {
> +                       dev_err(&pdev->dev, "failed to request otg_id irq\n");
> +                       goto err;
> +               }
> +       }
> +
> +       platform_set_drvdata(pdev, extcon_data);
> +       /* Perform initial detection */
> +       odroid_usbotg_detect_cable(extcon_data);
> +
> +       dev_dbg(&pdev->dev, "probe: success\n");
> +
> +       return 0;
> +
> +err:
> +       extcon_dev_unregister(extcon_data->edev);
> +
> +       return ret;
> +}
> +
> +static int odroid_usbotg_remove(struct platform_device *pdev)
> +{
> +       struct odroid_usbotg_data *extcon_data = platform_get_drvdata(pdev);
> +
> +       free_irq(extcon_data->vbus_det_irq, extcon_data);
> +       if (extcon_data->otg_id)
> +               free_irq(extcon_data->otg_id_irq, extcon_data);
> +       extcon_dev_unregister(extcon_data->edev);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id odroid_usbotg_of_match[] = {
> +       { .compatible = "extcon-odroid-usbotg" },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(of, odroid_usbotg_of_match);
> +
> +static struct platform_driver odroid_usbotg_driver = {
> +       .probe          = odroid_usbotg_probe,
> +       .remove         = odroid_usbotg_remove,
> +       .driver         = {
> +               .name   = "odroid-usbotg",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(odroid_usbotg_of_match)
> +       },
> +};
> +
> +static int __init odroid_usbotg_init(void)
> +{
> +       return platform_driver_register(&odroid_usbotg_driver);
> +}
> +
> +subsys_initcall(odroid_usbotg_init);
> +
> +static void __exit odroid_usbotg_cleanup(void)
> +{
> +       platform_driver_unregister(&odroid_usbotg_driver);
> +}
> +
> +module_exit(odroid_usbotg_cleanup);
> +
> +MODULE_AUTHOR("Lukasz Stelmach <l.stelmach@samsung.com>, Robert Baldyga <r.baldyga@samsung.com>");
> +MODULE_DESCRIPTION("USB OTG extcon driver for Odroid U3, U3+ and X");
> +MODULE_LICENSE("GPL");
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-19  8:50   ` George Cherian
@ 2015-03-19 12:07     ` Robert Baldyga
  2015-03-19 12:19       ` George Cherian
  0 siblings, 1 reply; 32+ messages in thread
From: Robert Baldyga @ 2015-03-19 12:07 UTC (permalink / raw)
  To: George Cherian
  Cc: balbi, gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	m.szyprowski, Łukasz Stelmach

Hi George,

On 03/19/2015 09:50 AM, George Cherian wrote:
> Hi Robert,
> 
> This looks like a extcon driver based on gpio for USB.
> 
> Roger posted a generic one a while back.
> https://lkml.org/lkml/2015/2/2/187
> 
> Doesn't this serve the purpose rather than adding this driver?

Roger's driver doesn't support VBUS state detection so it cannot handle
situation when USB cable is unpluged. In addition some of Odroid boards
has only VBUS detection (without ID pin), so this driver cannot handle
them at all.

Best regards,
Robert

> 
> On Wed, Mar 18, 2015 at 7:34 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>> This patch adds extcon driver for Odroid U3, U3+ and X boards.
>> It recognizes type of USB cable connected to Odroid board basing on
>> two signal lines VBUS_DET and OTG_ID (the second one is present only
>> on Odroid U3+ board).
>>
>> Following table of states presents relationship between this signals
>> and detected cable type:
>>
>> state    | VBUS_DET |  OTG_ID
>> -------------------------------
>> USB      |    H     |    H
>> USB_HOST |    H     |    L
>> disconn. |    L     |    H
>> USB-HOST |    L     |    L
>>
>> This driver is based on extcon-gpio driver.
>>
>> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
>> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
>> ---
>>  drivers/extcon/Kconfig                |   4 +
>>  drivers/extcon/Makefile               |   1 +
>>  drivers/extcon/extcon-odroid-usbotg.c | 256 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 261 insertions(+)
>>  create mode 100644 drivers/extcon/extcon-odroid-usbotg.c
>>
>> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
>> index 6a1f7de..891dca3 100644
>> --- a/drivers/extcon/Kconfig
>> +++ b/drivers/extcon/Kconfig
>> @@ -93,4 +93,8 @@ config EXTCON_SM5502
>>           Silicon Mitus SM5502. The SM5502 is a USB port accessory
>>           detector and switch.
>>
>> +config EXTCON_ODROID_USBOTG
>> +       tristate "Extcon Odroid U3, U3+, X and XU USB OTG port"
>> +       depends on OF_GPIO
>> +
>>  endif # MULTISTATE_SWITCH
>> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
>> index 0370b42..514384e 100644
>> --- a/drivers/extcon/Makefile
>> +++ b/drivers/extcon/Makefile
>> @@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997)  += extcon-max8997.o
>>  obj-$(CONFIG_EXTCON_PALMAS)    += extcon-palmas.o
>>  obj-$(CONFIG_EXTCON_RT8973A)   += extcon-rt8973a.o
>>  obj-$(CONFIG_EXTCON_SM5502)    += extcon-sm5502.o
>> +obj-$(CONFIG_EXTCON_ODROID_USBOTG) += extcon-odroid-usbotg.o
>> diff --git a/drivers/extcon/extcon-odroid-usbotg.c b/drivers/extcon/extcon-odroid-usbotg.c
>> new file mode 100644
>> index 0000000..7f71c48
>> --- /dev/null
>> +++ b/drivers/extcon/extcon-odroid-usbotg.c
>> @@ -0,0 +1,256 @@
>> +/*
>> + *  drivers/extcon/extcon-odroid-usbotg.c
>> + *
>> + *  USB cable extcon driver for Odroid U3, Odroid U3+ and Odroid X
>> + *
>> + * Copyright (C) 2014 Samsung Electronics
>> + * Author: Lukasz Stelmach <l.stelmach@samsung.com>
>> + * Author: Robert Baldyga <r.baldyga@samsung.com>
>> + *
>> + * based on drivers/extcon/extcon-gpio.c
>> + * Copyright (C) 2008 Google, Inc.
>> + * Author: Mike Lockwood <lockwood@android.com>
>> + *
>> + * This software is licensed under the terms of the GNU General Public
>> + * License version 2, as published by the Free Software Foundation, and
>> + * may be copied, distributed, and modified under those terms.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <linux/init.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/gpio.h>
>> +#include <linux/of_gpio.h>
>> +#include <linux/extcon.h>
>> +#include <linux/extcon/extcon-gpio.h>
>> +#include <linux/delay.h>
>> +
>> +enum {
>> +       EXTCON_CABLE_USB = 0,
>> +       EXTCON_CABLE_USB_HOST,
>> +
>> +       _EXTCON_CABLE_NUM,
>> +};
>> +
>> +static const char * const odroid_usbotg_cable[] = {
>> +       [EXTCON_CABLE_USB] = "USB",
>> +       [EXTCON_CABLE_USB_HOST] = "USB-HOST",
>> +
>> +       NULL,
>> +};
>> +
>> +struct odroid_usbotg_data {
>> +       struct extcon_dev *edev;
>> +       struct gpio_desc *otg_id;
>> +       struct gpio_desc *vbus_det;
>> +       int otg_id_irq;
>> +       int vbus_det_irq;
>> +       unsigned long debounce_ms;
>> +};
>> +
>> +/*
>> + * state    | VBUS_DET |  OTG_ID
>> + * -------------------------------
>> + * USB      |    H     |    H
>> + * USB-HOST |    H     |    L
>> + * disconn. |    L     |    H
>> + * USB-HOST |    L     |    L
>> + *
>> + * Only Odroid U3+ has OTG_ID line. U3 and X versions can detect only
>> + * USB slave cable.
>> + */
>> +
>> +static void odroid_usbotg_detect_cable(struct odroid_usbotg_data *extcon_data)
>> +{
>> +       int state;
>> +
>> +       mdelay(extcon_data->debounce_ms);
>> +
>> +       if (extcon_data->otg_id)
>> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) |
>> +                       gpiod_get_value(extcon_data->otg_id);
>> +       else
>> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) | 1;
>> +
>> +       dev_dbg(&extcon_data->edev->dev, "cable state changed to %d\n", state);
>> +
>> +       if (state & 0x1)
>> +               extcon_set_cable_state_(extcon_data->edev,
>> +                       EXTCON_CABLE_USB_HOST, false);
>> +       if (state != 0x3)
>> +               extcon_set_cable_state_(extcon_data->edev,
>> +                       EXTCON_CABLE_USB, false);
>> +
>> +       if (!(state & 0x1))
>> +               extcon_set_cable_state_(extcon_data->edev,
>> +                       EXTCON_CABLE_USB_HOST, true);
>> +       else if (state == 0x3)
>> +               extcon_set_cable_state_(extcon_data->edev,
>> +                       EXTCON_CABLE_USB, true);
>> +}
>> +
>> +static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
>> +{
>> +       struct odroid_usbotg_data *extcon_data = dev_id;
>> +
>> +       odroid_usbotg_detect_cable(extcon_data);
>> +
>> +       return IRQ_HANDLED;
>> +}
>> +
>> +static int odroid_usbotg_parse_dt(struct platform_device *pdev,
>> +                                   struct odroid_usbotg_data *extcon_data)
>> +{
>> +       struct device_node *np = pdev->dev.of_node;
>> +       u32 val;
>> +
>> +       if (!np)
>> +               return -ENODEV;
>> +
>> +       extcon_data->edev->name = np->name;
>> +
>> +       if (of_property_read_u32(np, "debounce", &val) != 0)
>> +               val = 50;
>> +       extcon_data->debounce_ms = val;
>> +
>> +       return 0;
>> +}
>> +
>> +static int odroid_usbotg_probe(struct platform_device *pdev)
>> +{
>> +       struct odroid_usbotg_data *extcon_data;
>> +       int ret = 0;
>> +
>> +       extcon_data = devm_kzalloc(&pdev->dev,
>> +               sizeof(struct odroid_usbotg_data), GFP_KERNEL);
>> +       if (!extcon_data)
>> +               return -ENOMEM;
>> +
>> +       extcon_data->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
>> +                                        GFP_KERNEL);
>> +       if (IS_ERR(extcon_data->edev)) {
>> +               dev_err(&pdev->dev, "failed to allocate extcon device\n");
>> +               return -ENOMEM;
>> +       }
>> +       extcon_data->edev->supported_cable = odroid_usbotg_cable;
>> +
>> +       ret = odroid_usbotg_parse_dt(pdev, extcon_data);
>> +       if (IS_ERR_VALUE(ret)) {
>> +               dev_err(&pdev->dev, "failed to get data from device tree\n");
>> +               return ret;
>> +       }
>> +
>> +       /* gpios */
>> +       extcon_data->vbus_det = devm_gpiod_get(&pdev->dev, "vbus-det");
>> +       if (IS_ERR(extcon_data->vbus_det)) {
>> +               dev_err(&pdev->dev, "failed to get vbus_det gpio\n");
>> +               return PTR_ERR(extcon_data->vbus_det);
>> +       }
>> +       extcon_data->otg_id = devm_gpiod_get_optional(&pdev->dev, "otg-id");
>> +
>> +       extcon_data->edev->dev.parent = &pdev->dev;
>> +       ret = extcon_dev_register(extcon_data->edev);
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       /* irq */
>> +       extcon_data->vbus_det_irq = gpiod_to_irq(extcon_data->vbus_det);
>> +       if (extcon_data->vbus_det_irq < 0) {
>> +               dev_err(&pdev->dev, "failed to get irq from vbus_det\n");
>> +               ret = extcon_data->vbus_det_irq;
>> +               goto err;
>> +       }
>> +       ret = request_threaded_irq(extcon_data->vbus_det_irq, NULL,
>> +                                  gpio_irq_handler, IRQF_ONESHOT |
>> +                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
>> +                                  pdev->name, extcon_data);
>> +       if (ret < 0) {
>> +               dev_err(&pdev->dev, "failed to request vbus_det irq\n");
>> +               goto err;
>> +       }
>> +
>> +       if (extcon_data->otg_id) {
>> +               extcon_data->otg_id_irq = gpiod_to_irq(extcon_data->otg_id);
>> +               if (extcon_data->otg_id_irq < 0) {
>> +                       dev_err(&pdev->dev, "failed to get irq from otg_id\n");
>> +                       ret = extcon_data->otg_id_irq;
>> +                       goto err;
>> +               }
>> +               ret = request_threaded_irq(extcon_data->otg_id_irq, NULL,
>> +                               gpio_irq_handler, IRQF_ONESHOT |
>> +                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
>> +                               pdev->name, extcon_data);
>> +               if (ret < 0) {
>> +                       dev_err(&pdev->dev, "failed to request otg_id irq\n");
>> +                       goto err;
>> +               }
>> +       }
>> +
>> +       platform_set_drvdata(pdev, extcon_data);
>> +       /* Perform initial detection */
>> +       odroid_usbotg_detect_cable(extcon_data);
>> +
>> +       dev_dbg(&pdev->dev, "probe: success\n");
>> +
>> +       return 0;
>> +
>> +err:
>> +       extcon_dev_unregister(extcon_data->edev);
>> +
>> +       return ret;
>> +}
>> +
>> +static int odroid_usbotg_remove(struct platform_device *pdev)
>> +{
>> +       struct odroid_usbotg_data *extcon_data = platform_get_drvdata(pdev);
>> +
>> +       free_irq(extcon_data->vbus_det_irq, extcon_data);
>> +       if (extcon_data->otg_id)
>> +               free_irq(extcon_data->otg_id_irq, extcon_data);
>> +       extcon_dev_unregister(extcon_data->edev);
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct of_device_id odroid_usbotg_of_match[] = {
>> +       { .compatible = "extcon-odroid-usbotg" },
>> +       { },
>> +};
>> +MODULE_DEVICE_TABLE(of, odroid_usbotg_of_match);
>> +
>> +static struct platform_driver odroid_usbotg_driver = {
>> +       .probe          = odroid_usbotg_probe,
>> +       .remove         = odroid_usbotg_remove,
>> +       .driver         = {
>> +               .name   = "odroid-usbotg",
>> +               .owner  = THIS_MODULE,
>> +               .of_match_table = of_match_ptr(odroid_usbotg_of_match)
>> +       },
>> +};
>> +
>> +static int __init odroid_usbotg_init(void)
>> +{
>> +       return platform_driver_register(&odroid_usbotg_driver);
>> +}
>> +
>> +subsys_initcall(odroid_usbotg_init);
>> +
>> +static void __exit odroid_usbotg_cleanup(void)
>> +{
>> +       platform_driver_unregister(&odroid_usbotg_driver);
>> +}
>> +
>> +module_exit(odroid_usbotg_cleanup);
>> +
>> +MODULE_AUTHOR("Lukasz Stelmach <l.stelmach@samsung.com>, Robert Baldyga <r.baldyga@samsung.com>");
>> +MODULE_DESCRIPTION("USB OTG extcon driver for Odroid U3, U3+ and X");
>> +MODULE_LICENSE("GPL");
>> --
>> 1.9.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-19 12:07     ` Robert Baldyga
@ 2015-03-19 12:19       ` George Cherian
  2015-03-19 14:45         ` Roger Quadros
  0 siblings, 1 reply; 32+ messages in thread
From: George Cherian @ 2015-03-19 12:19 UTC (permalink / raw)
  To: Robert Baldyga
  Cc: balbi, gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	Marek Szyprowski, Łukasz Stelmach, rogerq

Hi Robert,

+Roger
On Thu, Mar 19, 2015 at 5:37 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
> Hi George,
>
> On 03/19/2015 09:50 AM, George Cherian wrote:
>> Hi Robert,
>>
>> This looks like a extcon driver based on gpio for USB.
>>
>> Roger posted a generic one a while back.
>> https://lkml.org/lkml/2015/2/2/187
>>
>> Doesn't this serve the purpose rather than adding this driver?
>
> Roger's driver doesn't support VBUS state detection so it cannot handle
I feel Roger's driver could be extended for supporting VBUS.
Also I think Roger's driver is about to get merged.
Probably, Roger or Chanwoo can better tell that

> situation when USB cable is unpluged. In addition some of Odroid boards
> has only VBUS detection (without ID pin), so this driver cannot handle
> them at all.
>
> Best regards,
> Robert
>
>>
>> On Wed, Mar 18, 2015 at 7:34 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>>> This patch adds extcon driver for Odroid U3, U3+ and X boards.
>>> It recognizes type of USB cable connected to Odroid board basing on
>>> two signal lines VBUS_DET and OTG_ID (the second one is present only
>>> on Odroid U3+ board).
>>>
>>> Following table of states presents relationship between this signals
>>> and detected cable type:
>>>
>>> state    | VBUS_DET |  OTG_ID
>>> -------------------------------
>>> USB      |    H     |    H
>>> USB_HOST |    H     |    L
>>> disconn. |    L     |    H
>>> USB-HOST |    L     |    L
>>>
>>> This driver is based on extcon-gpio driver.
>>>
>>> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
>>> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
>>> ---
>>>  drivers/extcon/Kconfig                |   4 +
>>>  drivers/extcon/Makefile               |   1 +
>>>  drivers/extcon/extcon-odroid-usbotg.c | 256 ++++++++++++++++++++++++++++++++++
>>>  3 files changed, 261 insertions(+)
>>>  create mode 100644 drivers/extcon/extcon-odroid-usbotg.c
>>>
>>> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
>>> index 6a1f7de..891dca3 100644
>>> --- a/drivers/extcon/Kconfig
>>> +++ b/drivers/extcon/Kconfig
>>> @@ -93,4 +93,8 @@ config EXTCON_SM5502
>>>           Silicon Mitus SM5502. The SM5502 is a USB port accessory
>>>           detector and switch.
>>>
>>> +config EXTCON_ODROID_USBOTG
>>> +       tristate "Extcon Odroid U3, U3+, X and XU USB OTG port"
>>> +       depends on OF_GPIO
>>> +
>>>  endif # MULTISTATE_SWITCH
>>> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
>>> index 0370b42..514384e 100644
>>> --- a/drivers/extcon/Makefile
>>> +++ b/drivers/extcon/Makefile
>>> @@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997)  += extcon-max8997.o
>>>  obj-$(CONFIG_EXTCON_PALMAS)    += extcon-palmas.o
>>>  obj-$(CONFIG_EXTCON_RT8973A)   += extcon-rt8973a.o
>>>  obj-$(CONFIG_EXTCON_SM5502)    += extcon-sm5502.o
>>> +obj-$(CONFIG_EXTCON_ODROID_USBOTG) += extcon-odroid-usbotg.o
>>> diff --git a/drivers/extcon/extcon-odroid-usbotg.c b/drivers/extcon/extcon-odroid-usbotg.c
>>> new file mode 100644
>>> index 0000000..7f71c48
>>> --- /dev/null
>>> +++ b/drivers/extcon/extcon-odroid-usbotg.c
>>> @@ -0,0 +1,256 @@
>>> +/*
>>> + *  drivers/extcon/extcon-odroid-usbotg.c
>>> + *
>>> + *  USB cable extcon driver for Odroid U3, Odroid U3+ and Odroid X
>>> + *
>>> + * Copyright (C) 2014 Samsung Electronics
>>> + * Author: Lukasz Stelmach <l.stelmach@samsung.com>
>>> + * Author: Robert Baldyga <r.baldyga@samsung.com>
>>> + *
>>> + * based on drivers/extcon/extcon-gpio.c
>>> + * Copyright (C) 2008 Google, Inc.
>>> + * Author: Mike Lockwood <lockwood@android.com>
>>> + *
>>> + * This software is licensed under the terms of the GNU General Public
>>> + * License version 2, as published by the Free Software Foundation, and
>>> + * may be copied, distributed, and modified under those terms.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + */
>>> +
>>> +#include <linux/module.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/init.h>
>>> +#include <linux/interrupt.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/gpio.h>
>>> +#include <linux/of_gpio.h>
>>> +#include <linux/extcon.h>
>>> +#include <linux/extcon/extcon-gpio.h>
>>> +#include <linux/delay.h>
>>> +
>>> +enum {
>>> +       EXTCON_CABLE_USB = 0,
>>> +       EXTCON_CABLE_USB_HOST,
>>> +
>>> +       _EXTCON_CABLE_NUM,
>>> +};
>>> +
>>> +static const char * const odroid_usbotg_cable[] = {
>>> +       [EXTCON_CABLE_USB] = "USB",
>>> +       [EXTCON_CABLE_USB_HOST] = "USB-HOST",
>>> +
>>> +       NULL,
>>> +};
>>> +
>>> +struct odroid_usbotg_data {
>>> +       struct extcon_dev *edev;
>>> +       struct gpio_desc *otg_id;
>>> +       struct gpio_desc *vbus_det;
>>> +       int otg_id_irq;
>>> +       int vbus_det_irq;
>>> +       unsigned long debounce_ms;
>>> +};
>>> +
>>> +/*
>>> + * state    | VBUS_DET |  OTG_ID
>>> + * -------------------------------
>>> + * USB      |    H     |    H
>>> + * USB-HOST |    H     |    L
>>> + * disconn. |    L     |    H
>>> + * USB-HOST |    L     |    L
>>> + *
>>> + * Only Odroid U3+ has OTG_ID line. U3 and X versions can detect only
>>> + * USB slave cable.
>>> + */
>>> +
>>> +static void odroid_usbotg_detect_cable(struct odroid_usbotg_data *extcon_data)
>>> +{
>>> +       int state;
>>> +
>>> +       mdelay(extcon_data->debounce_ms);
>>> +
>>> +       if (extcon_data->otg_id)
>>> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) |
>>> +                       gpiod_get_value(extcon_data->otg_id);
>>> +       else
>>> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) | 1;
>>> +
>>> +       dev_dbg(&extcon_data->edev->dev, "cable state changed to %d\n", state);
>>> +
>>> +       if (state & 0x1)
>>> +               extcon_set_cable_state_(extcon_data->edev,
>>> +                       EXTCON_CABLE_USB_HOST, false);
>>> +       if (state != 0x3)
>>> +               extcon_set_cable_state_(extcon_data->edev,
>>> +                       EXTCON_CABLE_USB, false);
>>> +
>>> +       if (!(state & 0x1))
>>> +               extcon_set_cable_state_(extcon_data->edev,
>>> +                       EXTCON_CABLE_USB_HOST, true);
>>> +       else if (state == 0x3)
>>> +               extcon_set_cable_state_(extcon_data->edev,
>>> +                       EXTCON_CABLE_USB, true);
>>> +}
>>> +
>>> +static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
>>> +{
>>> +       struct odroid_usbotg_data *extcon_data = dev_id;
>>> +
>>> +       odroid_usbotg_detect_cable(extcon_data);
>>> +
>>> +       return IRQ_HANDLED;
>>> +}
>>> +
>>> +static int odroid_usbotg_parse_dt(struct platform_device *pdev,
>>> +                                   struct odroid_usbotg_data *extcon_data)
>>> +{
>>> +       struct device_node *np = pdev->dev.of_node;
>>> +       u32 val;
>>> +
>>> +       if (!np)
>>> +               return -ENODEV;
>>> +
>>> +       extcon_data->edev->name = np->name;
>>> +
>>> +       if (of_property_read_u32(np, "debounce", &val) != 0)
>>> +               val = 50;
>>> +       extcon_data->debounce_ms = val;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int odroid_usbotg_probe(struct platform_device *pdev)
>>> +{
>>> +       struct odroid_usbotg_data *extcon_data;
>>> +       int ret = 0;
>>> +
>>> +       extcon_data = devm_kzalloc(&pdev->dev,
>>> +               sizeof(struct odroid_usbotg_data), GFP_KERNEL);
>>> +       if (!extcon_data)
>>> +               return -ENOMEM;
>>> +
>>> +       extcon_data->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
>>> +                                        GFP_KERNEL);
>>> +       if (IS_ERR(extcon_data->edev)) {
>>> +               dev_err(&pdev->dev, "failed to allocate extcon device\n");
>>> +               return -ENOMEM;
>>> +       }
>>> +       extcon_data->edev->supported_cable = odroid_usbotg_cable;
>>> +
>>> +       ret = odroid_usbotg_parse_dt(pdev, extcon_data);
>>> +       if (IS_ERR_VALUE(ret)) {
>>> +               dev_err(&pdev->dev, "failed to get data from device tree\n");
>>> +               return ret;
>>> +       }
>>> +
>>> +       /* gpios */
>>> +       extcon_data->vbus_det = devm_gpiod_get(&pdev->dev, "vbus-det");
>>> +       if (IS_ERR(extcon_data->vbus_det)) {
>>> +               dev_err(&pdev->dev, "failed to get vbus_det gpio\n");
>>> +               return PTR_ERR(extcon_data->vbus_det);
>>> +       }
>>> +       extcon_data->otg_id = devm_gpiod_get_optional(&pdev->dev, "otg-id");
>>> +
>>> +       extcon_data->edev->dev.parent = &pdev->dev;
>>> +       ret = extcon_dev_register(extcon_data->edev);
>>> +       if (ret < 0)
>>> +               return ret;
>>> +
>>> +       /* irq */
>>> +       extcon_data->vbus_det_irq = gpiod_to_irq(extcon_data->vbus_det);
>>> +       if (extcon_data->vbus_det_irq < 0) {
>>> +               dev_err(&pdev->dev, "failed to get irq from vbus_det\n");
>>> +               ret = extcon_data->vbus_det_irq;
>>> +               goto err;
>>> +       }
>>> +       ret = request_threaded_irq(extcon_data->vbus_det_irq, NULL,
>>> +                                  gpio_irq_handler, IRQF_ONESHOT |
>>> +                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
>>> +                                  pdev->name, extcon_data);
>>> +       if (ret < 0) {
>>> +               dev_err(&pdev->dev, "failed to request vbus_det irq\n");
>>> +               goto err;
>>> +       }
>>> +
>>> +       if (extcon_data->otg_id) {
>>> +               extcon_data->otg_id_irq = gpiod_to_irq(extcon_data->otg_id);
>>> +               if (extcon_data->otg_id_irq < 0) {
>>> +                       dev_err(&pdev->dev, "failed to get irq from otg_id\n");
>>> +                       ret = extcon_data->otg_id_irq;
>>> +                       goto err;
>>> +               }
>>> +               ret = request_threaded_irq(extcon_data->otg_id_irq, NULL,
>>> +                               gpio_irq_handler, IRQF_ONESHOT |
>>> +                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
>>> +                               pdev->name, extcon_data);
>>> +               if (ret < 0) {
>>> +                       dev_err(&pdev->dev, "failed to request otg_id irq\n");
>>> +                       goto err;
>>> +               }
>>> +       }
>>> +
>>> +       platform_set_drvdata(pdev, extcon_data);
>>> +       /* Perform initial detection */
>>> +       odroid_usbotg_detect_cable(extcon_data);
>>> +
>>> +       dev_dbg(&pdev->dev, "probe: success\n");
>>> +
>>> +       return 0;
>>> +
>>> +err:
>>> +       extcon_dev_unregister(extcon_data->edev);
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int odroid_usbotg_remove(struct platform_device *pdev)
>>> +{
>>> +       struct odroid_usbotg_data *extcon_data = platform_get_drvdata(pdev);
>>> +
>>> +       free_irq(extcon_data->vbus_det_irq, extcon_data);
>>> +       if (extcon_data->otg_id)
>>> +               free_irq(extcon_data->otg_id_irq, extcon_data);
>>> +       extcon_dev_unregister(extcon_data->edev);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static const struct of_device_id odroid_usbotg_of_match[] = {
>>> +       { .compatible = "extcon-odroid-usbotg" },
>>> +       { },
>>> +};
>>> +MODULE_DEVICE_TABLE(of, odroid_usbotg_of_match);
>>> +
>>> +static struct platform_driver odroid_usbotg_driver = {
>>> +       .probe          = odroid_usbotg_probe,
>>> +       .remove         = odroid_usbotg_remove,
>>> +       .driver         = {
>>> +               .name   = "odroid-usbotg",
>>> +               .owner  = THIS_MODULE,
>>> +               .of_match_table = of_match_ptr(odroid_usbotg_of_match)
>>> +       },
>>> +};
>>> +
>>> +static int __init odroid_usbotg_init(void)
>>> +{
>>> +       return platform_driver_register(&odroid_usbotg_driver);
>>> +}
>>> +
>>> +subsys_initcall(odroid_usbotg_init);
>>> +
>>> +static void __exit odroid_usbotg_cleanup(void)
>>> +{
>>> +       platform_driver_unregister(&odroid_usbotg_driver);
>>> +}
>>> +
>>> +module_exit(odroid_usbotg_cleanup);
>>> +
>>> +MODULE_AUTHOR("Lukasz Stelmach <l.stelmach@samsung.com>, Robert Baldyga <r.baldyga@samsung.com>");
>>> +MODULE_DESCRIPTION("USB OTG extcon driver for Odroid U3, U3+ and X");
>>> +MODULE_LICENSE("GPL");
>>> --
>>> 1.9.1
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>

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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-19 12:19       ` George Cherian
@ 2015-03-19 14:45         ` Roger Quadros
  2015-03-19 20:50           ` Chanwoo Choi
  0 siblings, 1 reply; 32+ messages in thread
From: Roger Quadros @ 2015-03-19 14:45 UTC (permalink / raw)
  To: George Cherian, Robert Baldyga
  Cc: balbi, gregkh, myungjoo.ham, cw00.choi, linux-usb, linux-kernel,
	Marek Szyprowski, Łukasz Stelmach

On 19/03/15 14:19, George Cherian wrote:
> Hi Robert,
> 
> +Roger
> On Thu, Mar 19, 2015 at 5:37 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>> Hi George,
>>
>> On 03/19/2015 09:50 AM, George Cherian wrote:
>>> Hi Robert,
>>>
>>> This looks like a extcon driver based on gpio for USB.
>>>
>>> Roger posted a generic one a while back.
>>> https://lkml.org/lkml/2015/2/2/187
>>>
>>> Doesn't this serve the purpose rather than adding this driver?
>>
>> Roger's driver doesn't support VBUS state detection so it cannot handle
> I feel Roger's driver could be extended for supporting VBUS.
> Also I think Roger's driver is about to get merged.
> Probably, Roger or Chanwoo can better tell that

It is already queued for 4.1 and is available in linux-next.

> 
>> situation when USB cable is unpluged. In addition some of Odroid boards
>> has only VBUS detection (without ID pin), so this driver cannot handle
>> them at all.

why not?

x15-beagleboard also gets VBUS event over GPIO and I was planning to extent it
to support VBUS detection.

cheers,
-roger

>>
>> Best regards,
>> Robert
>>
>>>
>>> On Wed, Mar 18, 2015 at 7:34 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>>>> This patch adds extcon driver for Odroid U3, U3+ and X boards.
>>>> It recognizes type of USB cable connected to Odroid board basing on
>>>> two signal lines VBUS_DET and OTG_ID (the second one is present only
>>>> on Odroid U3+ board).
>>>>
>>>> Following table of states presents relationship between this signals
>>>> and detected cable type:
>>>>
>>>> state    | VBUS_DET |  OTG_ID
>>>> -------------------------------
>>>> USB      |    H     |    H
>>>> USB_HOST |    H     |    L
>>>> disconn. |    L     |    H
>>>> USB-HOST |    L     |    L
>>>>
>>>> This driver is based on extcon-gpio driver.
>>>>
>>>> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
>>>> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
>>>> ---
>>>>  drivers/extcon/Kconfig                |   4 +
>>>>  drivers/extcon/Makefile               |   1 +
>>>>  drivers/extcon/extcon-odroid-usbotg.c | 256 ++++++++++++++++++++++++++++++++++
>>>>  3 files changed, 261 insertions(+)
>>>>  create mode 100644 drivers/extcon/extcon-odroid-usbotg.c
>>>>
>>>> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
>>>> index 6a1f7de..891dca3 100644
>>>> --- a/drivers/extcon/Kconfig
>>>> +++ b/drivers/extcon/Kconfig
>>>> @@ -93,4 +93,8 @@ config EXTCON_SM5502
>>>>           Silicon Mitus SM5502. The SM5502 is a USB port accessory
>>>>           detector and switch.
>>>>
>>>> +config EXTCON_ODROID_USBOTG
>>>> +       tristate "Extcon Odroid U3, U3+, X and XU USB OTG port"
>>>> +       depends on OF_GPIO
>>>> +
>>>>  endif # MULTISTATE_SWITCH
>>>> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
>>>> index 0370b42..514384e 100644
>>>> --- a/drivers/extcon/Makefile
>>>> +++ b/drivers/extcon/Makefile
>>>> @@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997)  += extcon-max8997.o
>>>>  obj-$(CONFIG_EXTCON_PALMAS)    += extcon-palmas.o
>>>>  obj-$(CONFIG_EXTCON_RT8973A)   += extcon-rt8973a.o
>>>>  obj-$(CONFIG_EXTCON_SM5502)    += extcon-sm5502.o
>>>> +obj-$(CONFIG_EXTCON_ODROID_USBOTG) += extcon-odroid-usbotg.o
>>>> diff --git a/drivers/extcon/extcon-odroid-usbotg.c b/drivers/extcon/extcon-odroid-usbotg.c
>>>> new file mode 100644
>>>> index 0000000..7f71c48
>>>> --- /dev/null
>>>> +++ b/drivers/extcon/extcon-odroid-usbotg.c
>>>> @@ -0,0 +1,256 @@
>>>> +/*
>>>> + *  drivers/extcon/extcon-odroid-usbotg.c
>>>> + *
>>>> + *  USB cable extcon driver for Odroid U3, Odroid U3+ and Odroid X
>>>> + *
>>>> + * Copyright (C) 2014 Samsung Electronics
>>>> + * Author: Lukasz Stelmach <l.stelmach@samsung.com>
>>>> + * Author: Robert Baldyga <r.baldyga@samsung.com>
>>>> + *
>>>> + * based on drivers/extcon/extcon-gpio.c
>>>> + * Copyright (C) 2008 Google, Inc.
>>>> + * Author: Mike Lockwood <lockwood@android.com>
>>>> + *
>>>> + * This software is licensed under the terms of the GNU General Public
>>>> + * License version 2, as published by the Free Software Foundation, and
>>>> + * may be copied, distributed, and modified under those terms.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + */
>>>> +
>>>> +#include <linux/module.h>
>>>> +#include <linux/kernel.h>
>>>> +#include <linux/init.h>
>>>> +#include <linux/interrupt.h>
>>>> +#include <linux/platform_device.h>
>>>> +#include <linux/slab.h>
>>>> +#include <linux/gpio.h>
>>>> +#include <linux/of_gpio.h>
>>>> +#include <linux/extcon.h>
>>>> +#include <linux/extcon/extcon-gpio.h>
>>>> +#include <linux/delay.h>
>>>> +
>>>> +enum {
>>>> +       EXTCON_CABLE_USB = 0,
>>>> +       EXTCON_CABLE_USB_HOST,
>>>> +
>>>> +       _EXTCON_CABLE_NUM,
>>>> +};
>>>> +
>>>> +static const char * const odroid_usbotg_cable[] = {
>>>> +       [EXTCON_CABLE_USB] = "USB",
>>>> +       [EXTCON_CABLE_USB_HOST] = "USB-HOST",
>>>> +
>>>> +       NULL,
>>>> +};
>>>> +
>>>> +struct odroid_usbotg_data {
>>>> +       struct extcon_dev *edev;
>>>> +       struct gpio_desc *otg_id;
>>>> +       struct gpio_desc *vbus_det;
>>>> +       int otg_id_irq;
>>>> +       int vbus_det_irq;
>>>> +       unsigned long debounce_ms;
>>>> +};
>>>> +
>>>> +/*
>>>> + * state    | VBUS_DET |  OTG_ID
>>>> + * -------------------------------
>>>> + * USB      |    H     |    H
>>>> + * USB-HOST |    H     |    L
>>>> + * disconn. |    L     |    H
>>>> + * USB-HOST |    L     |    L
>>>> + *
>>>> + * Only Odroid U3+ has OTG_ID line. U3 and X versions can detect only
>>>> + * USB slave cable.
>>>> + */
>>>> +
>>>> +static void odroid_usbotg_detect_cable(struct odroid_usbotg_data *extcon_data)
>>>> +{
>>>> +       int state;
>>>> +
>>>> +       mdelay(extcon_data->debounce_ms);
>>>> +
>>>> +       if (extcon_data->otg_id)
>>>> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) |
>>>> +                       gpiod_get_value(extcon_data->otg_id);
>>>> +       else
>>>> +               state = (gpiod_get_value(extcon_data->vbus_det) << 1) | 1;
>>>> +
>>>> +       dev_dbg(&extcon_data->edev->dev, "cable state changed to %d\n", state);
>>>> +
>>>> +       if (state & 0x1)
>>>> +               extcon_set_cable_state_(extcon_data->edev,
>>>> +                       EXTCON_CABLE_USB_HOST, false);
>>>> +       if (state != 0x3)
>>>> +               extcon_set_cable_state_(extcon_data->edev,
>>>> +                       EXTCON_CABLE_USB, false);
>>>> +
>>>> +       if (!(state & 0x1))
>>>> +               extcon_set_cable_state_(extcon_data->edev,
>>>> +                       EXTCON_CABLE_USB_HOST, true);
>>>> +       else if (state == 0x3)
>>>> +               extcon_set_cable_state_(extcon_data->edev,
>>>> +                       EXTCON_CABLE_USB, true);
>>>> +}
>>>> +
>>>> +static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
>>>> +{
>>>> +       struct odroid_usbotg_data *extcon_data = dev_id;
>>>> +
>>>> +       odroid_usbotg_detect_cable(extcon_data);
>>>> +
>>>> +       return IRQ_HANDLED;
>>>> +}
>>>> +
>>>> +static int odroid_usbotg_parse_dt(struct platform_device *pdev,
>>>> +                                   struct odroid_usbotg_data *extcon_data)
>>>> +{
>>>> +       struct device_node *np = pdev->dev.of_node;
>>>> +       u32 val;
>>>> +
>>>> +       if (!np)
>>>> +               return -ENODEV;
>>>> +
>>>> +       extcon_data->edev->name = np->name;
>>>> +
>>>> +       if (of_property_read_u32(np, "debounce", &val) != 0)
>>>> +               val = 50;
>>>> +       extcon_data->debounce_ms = val;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int odroid_usbotg_probe(struct platform_device *pdev)
>>>> +{
>>>> +       struct odroid_usbotg_data *extcon_data;
>>>> +       int ret = 0;
>>>> +
>>>> +       extcon_data = devm_kzalloc(&pdev->dev,
>>>> +               sizeof(struct odroid_usbotg_data), GFP_KERNEL);
>>>> +       if (!extcon_data)
>>>> +               return -ENOMEM;
>>>> +
>>>> +       extcon_data->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
>>>> +                                        GFP_KERNEL);
>>>> +       if (IS_ERR(extcon_data->edev)) {
>>>> +               dev_err(&pdev->dev, "failed to allocate extcon device\n");
>>>> +               return -ENOMEM;
>>>> +       }
>>>> +       extcon_data->edev->supported_cable = odroid_usbotg_cable;
>>>> +
>>>> +       ret = odroid_usbotg_parse_dt(pdev, extcon_data);
>>>> +       if (IS_ERR_VALUE(ret)) {
>>>> +               dev_err(&pdev->dev, "failed to get data from device tree\n");
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       /* gpios */
>>>> +       extcon_data->vbus_det = devm_gpiod_get(&pdev->dev, "vbus-det");
>>>> +       if (IS_ERR(extcon_data->vbus_det)) {
>>>> +               dev_err(&pdev->dev, "failed to get vbus_det gpio\n");
>>>> +               return PTR_ERR(extcon_data->vbus_det);
>>>> +       }
>>>> +       extcon_data->otg_id = devm_gpiod_get_optional(&pdev->dev, "otg-id");
>>>> +
>>>> +       extcon_data->edev->dev.parent = &pdev->dev;
>>>> +       ret = extcon_dev_register(extcon_data->edev);
>>>> +       if (ret < 0)
>>>> +               return ret;
>>>> +
>>>> +       /* irq */
>>>> +       extcon_data->vbus_det_irq = gpiod_to_irq(extcon_data->vbus_det);
>>>> +       if (extcon_data->vbus_det_irq < 0) {
>>>> +               dev_err(&pdev->dev, "failed to get irq from vbus_det\n");
>>>> +               ret = extcon_data->vbus_det_irq;
>>>> +               goto err;
>>>> +       }
>>>> +       ret = request_threaded_irq(extcon_data->vbus_det_irq, NULL,
>>>> +                                  gpio_irq_handler, IRQF_ONESHOT |
>>>> +                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
>>>> +                                  pdev->name, extcon_data);
>>>> +       if (ret < 0) {
>>>> +               dev_err(&pdev->dev, "failed to request vbus_det irq\n");
>>>> +               goto err;
>>>> +       }
>>>> +
>>>> +       if (extcon_data->otg_id) {
>>>> +               extcon_data->otg_id_irq = gpiod_to_irq(extcon_data->otg_id);
>>>> +               if (extcon_data->otg_id_irq < 0) {
>>>> +                       dev_err(&pdev->dev, "failed to get irq from otg_id\n");
>>>> +                       ret = extcon_data->otg_id_irq;
>>>> +                       goto err;
>>>> +               }
>>>> +               ret = request_threaded_irq(extcon_data->otg_id_irq, NULL,
>>>> +                               gpio_irq_handler, IRQF_ONESHOT |
>>>> +                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
>>>> +                               pdev->name, extcon_data);
>>>> +               if (ret < 0) {
>>>> +                       dev_err(&pdev->dev, "failed to request otg_id irq\n");
>>>> +                       goto err;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       platform_set_drvdata(pdev, extcon_data);
>>>> +       /* Perform initial detection */
>>>> +       odroid_usbotg_detect_cable(extcon_data);
>>>> +
>>>> +       dev_dbg(&pdev->dev, "probe: success\n");
>>>> +
>>>> +       return 0;
>>>> +
>>>> +err:
>>>> +       extcon_dev_unregister(extcon_data->edev);
>>>> +
>>>> +       return ret;
>>>> +}
>>>> +
>>>> +static int odroid_usbotg_remove(struct platform_device *pdev)
>>>> +{
>>>> +       struct odroid_usbotg_data *extcon_data = platform_get_drvdata(pdev);
>>>> +
>>>> +       free_irq(extcon_data->vbus_det_irq, extcon_data);
>>>> +       if (extcon_data->otg_id)
>>>> +               free_irq(extcon_data->otg_id_irq, extcon_data);
>>>> +       extcon_dev_unregister(extcon_data->edev);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static const struct of_device_id odroid_usbotg_of_match[] = {
>>>> +       { .compatible = "extcon-odroid-usbotg" },
>>>> +       { },
>>>> +};
>>>> +MODULE_DEVICE_TABLE(of, odroid_usbotg_of_match);
>>>> +
>>>> +static struct platform_driver odroid_usbotg_driver = {
>>>> +       .probe          = odroid_usbotg_probe,
>>>> +       .remove         = odroid_usbotg_remove,
>>>> +       .driver         = {
>>>> +               .name   = "odroid-usbotg",
>>>> +               .owner  = THIS_MODULE,
>>>> +               .of_match_table = of_match_ptr(odroid_usbotg_of_match)
>>>> +       },
>>>> +};
>>>> +
>>>> +static int __init odroid_usbotg_init(void)
>>>> +{
>>>> +       return platform_driver_register(&odroid_usbotg_driver);
>>>> +}
>>>> +
>>>> +subsys_initcall(odroid_usbotg_init);
>>>> +
>>>> +static void __exit odroid_usbotg_cleanup(void)
>>>> +{
>>>> +       platform_driver_unregister(&odroid_usbotg_driver);
>>>> +}
>>>> +
>>>> +module_exit(odroid_usbotg_cleanup);
>>>> +
>>>> +MODULE_AUTHOR("Lukasz Stelmach <l.stelmach@samsung.com>, Robert Baldyga <r.baldyga@samsung.com>");
>>>> +MODULE_DESCRIPTION("USB OTG extcon driver for Odroid U3, U3+ and X");
>>>> +MODULE_LICENSE("GPL");
>>>> --
>>>> 1.9.1
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-19 14:45         ` Roger Quadros
@ 2015-03-19 20:50           ` Chanwoo Choi
  2015-03-20  7:25             ` Robert Baldyga
  0 siblings, 1 reply; 32+ messages in thread
From: Chanwoo Choi @ 2015-03-19 20:50 UTC (permalink / raw)
  To: Roger Quadros
  Cc: George Cherian, Robert Baldyga, Felipe Balbi, Greg KH,
	myungjoo.ham, Chanwoo Choi, linux-usb, linux-kernel,
	Marek Szyprowski, Łukasz Stelmach

Hi Roger,

On Thu, Mar 19, 2015 at 11:45 PM, Roger Quadros <rogerq@ti.com> wrote:
> On 19/03/15 14:19, George Cherian wrote:
>> Hi Robert,
>>
>> +Roger
>> On Thu, Mar 19, 2015 at 5:37 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>>> Hi George,
>>>
>>> On 03/19/2015 09:50 AM, George Cherian wrote:
>>>> Hi Robert,
>>>>
>>>> This looks like a extcon driver based on gpio for USB.
>>>>
>>>> Roger posted a generic one a while back.
>>>> https://lkml.org/lkml/2015/2/2/187
>>>>
>>>> Doesn't this serve the purpose rather than adding this driver?
>>>
>>> Roger's driver doesn't support VBUS state detection so it cannot handle
>> I feel Roger's driver could be extended for supporting VBUS.
>> Also I think Roger's driver is about to get merged.
>> Probably, Roger or Chanwoo can better tell that
>
> It is already queued for 4.1 and is available in linux-next.
>
>>
>>> situation when USB cable is unpluged. In addition some of Odroid boards
>>> has only VBUS detection (without ID pin), so this driver cannot handle
>>> them at all.
>
> why not?
>
> x15-beagleboard also gets VBUS event over GPIO and I was planning to extent it
> to support VBUS detection.

Sounds good to me to extent extcon-usb-gpio.c.
I'd like to hold only one extcon driver to support both USB and
USB-HOST with gpio .

There are one more extcon-gpio driver in mailing list as following:
- extcon-usb-gpio.c (will be merged to Linux 4.1)
- extcon-odroid-usbotg.c
- extcon-otg_gpio.c [1]
[1] https://lkml.org/lkml/2015/2/19/411

The each extcon gpio driver support both USB/USB-HOST cable by using
different way,
Because some board which detect USB/USB-HOST by gpio have a little
different pin composition

I think only one extcon driver can support all cases with optional properties.

Roger,
I'd like you to share your plan to extent the extcon-usb-gpio.c for
removing duplicate work.

[snip]

Thanks,
Chanwoo Choi

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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-19 20:50           ` Chanwoo Choi
@ 2015-03-20  7:25             ` Robert Baldyga
  2015-03-20  7:45               ` Chanwoo Choi
  0 siblings, 1 reply; 32+ messages in thread
From: Robert Baldyga @ 2015-03-20  7:25 UTC (permalink / raw)
  To: Chanwoo Choi, Roger Quadros
  Cc: George Cherian, Felipe Balbi, Greg KH, myungjoo.ham,
	Chanwoo Choi, linux-usb, linux-kernel, Marek Szyprowski,
	Łukasz Stelmach

Hi Chanwoo,

On 03/19/2015 09:50 PM, Chanwoo Choi wrote:
> Hi Roger,
> 
> On Thu, Mar 19, 2015 at 11:45 PM, Roger Quadros <rogerq@ti.com> wrote:
>> On 19/03/15 14:19, George Cherian wrote:
>>> Hi Robert,
>>>
>>> +Roger
>>> On Thu, Mar 19, 2015 at 5:37 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>>>> Hi George,
>>>>
>>>> On 03/19/2015 09:50 AM, George Cherian wrote:
>>>>> Hi Robert,
>>>>>
>>>>> This looks like a extcon driver based on gpio for USB.
>>>>>
>>>>> Roger posted a generic one a while back.
>>>>> https://lkml.org/lkml/2015/2/2/187
>>>>>
>>>>> Doesn't this serve the purpose rather than adding this driver?
>>>>
>>>> Roger's driver doesn't support VBUS state detection so it cannot handle
>>> I feel Roger's driver could be extended for supporting VBUS.
>>> Also I think Roger's driver is about to get merged.
>>> Probably, Roger or Chanwoo can better tell that
>>
>> It is already queued for 4.1 and is available in linux-next.
>>
>>>
>>>> situation when USB cable is unpluged. In addition some of Odroid boards
>>>> has only VBUS detection (without ID pin), so this driver cannot handle
>>>> them at all.
>>
>> why not?
>>
>> x15-beagleboard also gets VBUS event over GPIO and I was planning to extent it
>> to support VBUS detection.
> 
> Sounds good to me to extent extcon-usb-gpio.c.
> I'd like to hold only one extcon driver to support both USB and
> USB-HOST with gpio .
> 
> There are one more extcon-gpio driver in mailing list as following:
> - extcon-usb-gpio.c (will be merged to Linux 4.1)
> - extcon-odroid-usbotg.c
> - extcon-otg_gpio.c [1]
> [1] https://lkml.org/lkml/2015/2/19/411
> 
> The each extcon gpio driver support both USB/USB-HOST cable by using
> different way,
> Because some board which detect USB/USB-HOST by gpio have a little
> different pin composition

These differences are small. In general we have three cases:

1. We have both VBUS and ID pin detection - we can detect USB, USB-HOST
and cable disconnection.

2. We have only VBUS detection - we can detect USB and cable disconnection.

3. We have ID pin only - we can distinguish between USB and USB-HOST but
without ability to detect cable disconnection.

> 
> I think only one extcon driver can support all cases with optional properties.

So my driver in current form is ready for that. Only thing it would need
to change is to make VBUS detection an option (for now is mandatory
because all of supported Odroid boards have it). Then boards with VBUS
detection only or ID pin detection only will be handled also. I can also
change name of the driver to more generic. I'm going to prepare V2 on my
patches today.

Thanks,
Robert Baldyga

> 
> Roger,
> I'd like you to share your plan to extent the extcon-usb-gpio.c for
> removing duplicate work.
> 
> [snip]
> 
> Thanks,
> Chanwoo Choi
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-20  7:25             ` Robert Baldyga
@ 2015-03-20  7:45               ` Chanwoo Choi
  2015-03-20  8:51                 ` Roger Quadros
  0 siblings, 1 reply; 32+ messages in thread
From: Chanwoo Choi @ 2015-03-20  7:45 UTC (permalink / raw)
  To: Robert Baldyga
  Cc: Chanwoo Choi, Roger Quadros, George Cherian, Felipe Balbi,
	Greg KH, myungjoo.ham, linux-usb, linux-kernel, Marek Szyprowski,
	Łukasz Stelmach

Hi Robert,

On 03/20/2015 04:25 PM, Robert Baldyga wrote:
> Hi Chanwoo,
> 
> On 03/19/2015 09:50 PM, Chanwoo Choi wrote:
>> Hi Roger,
>>
>> On Thu, Mar 19, 2015 at 11:45 PM, Roger Quadros <rogerq@ti.com> wrote:
>>> On 19/03/15 14:19, George Cherian wrote:
>>>> Hi Robert,
>>>>
>>>> +Roger
>>>> On Thu, Mar 19, 2015 at 5:37 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>>>>> Hi George,
>>>>>
>>>>> On 03/19/2015 09:50 AM, George Cherian wrote:
>>>>>> Hi Robert,
>>>>>>
>>>>>> This looks like a extcon driver based on gpio for USB.
>>>>>>
>>>>>> Roger posted a generic one a while back.
>>>>>> https://lkml.org/lkml/2015/2/2/187
>>>>>>
>>>>>> Doesn't this serve the purpose rather than adding this driver?
>>>>>
>>>>> Roger's driver doesn't support VBUS state detection so it cannot handle
>>>> I feel Roger's driver could be extended for supporting VBUS.
>>>> Also I think Roger's driver is about to get merged.
>>>> Probably, Roger or Chanwoo can better tell that
>>>
>>> It is already queued for 4.1 and is available in linux-next.
>>>
>>>>
>>>>> situation when USB cable is unpluged. In addition some of Odroid boards
>>>>> has only VBUS detection (without ID pin), so this driver cannot handle
>>>>> them at all.
>>>
>>> why not?
>>>
>>> x15-beagleboard also gets VBUS event over GPIO and I was planning to extent it
>>> to support VBUS detection.
>>
>> Sounds good to me to extent extcon-usb-gpio.c.
>> I'd like to hold only one extcon driver to support both USB and
>> USB-HOST with gpio .
>>
>> There are one more extcon-gpio driver in mailing list as following:
>> - extcon-usb-gpio.c (will be merged to Linux 4.1)
>> - extcon-odroid-usbotg.c
>> - extcon-otg_gpio.c [1]
>> [1] https://lkml.org/lkml/2015/2/19/411
>>
>> The each extcon gpio driver support both USB/USB-HOST cable by using
>> different way,
>> Because some board which detect USB/USB-HOST by gpio have a little
>> different pin composition
> 
> These differences are small. In general we have three cases:
> 
> 1. We have both VBUS and ID pin detection - we can detect USB, USB-HOST
> and cable disconnection.
> 
> 2. We have only VBUS detection - we can detect USB and cable disconnection.
> 
> 3. We have ID pin only - we can distinguish between USB and USB-HOST but
> without ability to detect cable disconnection.
> 
>>
>> I think only one extcon driver can support all cases with optional properties.
> 
> So my driver in current form is ready for that. Only thing it would need
> to change is to make VBUS detection an option (for now is mandatory
> because all of supported Odroid boards have it). Then boards with VBUS
> detection only or ID pin detection only will be handled also. I can also
> change name of the driver to more generic. I'm going to prepare V2 on my
> patches today.

Could you implement this feature on extcon-usb-gpio.c to support various pin composition?
because extcon-usb-gpio.c was already implemented by Roger.
If you implement other extcon driver to detect USB/USB-HOST cable by using gpio,
there will be similar two extcon gpio driver for USB cable.

And,
As Roger comment, he have the plan to extend the extcon-usb-gpio.c.
So, If you will implement some feature for extcon driver with gpio,
I'd like you to share your plan this thread to remove duplicat work.

Thanks,
Chanwoo Choi

> 
> Thanks,
> Robert Baldyga
> 
>>
>> Roger,
>> I'd like you to share your plan to extent the extcon-usb-gpio.c for
>> removing duplicate work.
>>
>> [snip]
>>
>> Thanks,
>> Chanwoo Choi
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 


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

* Re: [RFC 01/19] extcon: add extcon-odroid-usbotg driver
  2015-03-20  7:45               ` Chanwoo Choi
@ 2015-03-20  8:51                 ` Roger Quadros
  0 siblings, 0 replies; 32+ messages in thread
From: Roger Quadros @ 2015-03-20  8:51 UTC (permalink / raw)
  To: Chanwoo Choi, Robert Baldyga
  Cc: Chanwoo Choi, George Cherian, Felipe Balbi, Greg KH,
	myungjoo.ham, linux-usb, linux-kernel, Marek Szyprowski,
	Łukasz Stelmach

Chanwoo & Robert,

On 20/03/15 09:45, Chanwoo Choi wrote:
> Hi Robert,
> 
> On 03/20/2015 04:25 PM, Robert Baldyga wrote:
>> Hi Chanwoo,
>>
>> On 03/19/2015 09:50 PM, Chanwoo Choi wrote:
>>> Hi Roger,
>>>
>>> On Thu, Mar 19, 2015 at 11:45 PM, Roger Quadros <rogerq@ti.com> wrote:
>>>> On 19/03/15 14:19, George Cherian wrote:
>>>>> Hi Robert,
>>>>>
>>>>> +Roger
>>>>> On Thu, Mar 19, 2015 at 5:37 PM, Robert Baldyga <r.baldyga@samsung.com> wrote:
>>>>>> Hi George,
>>>>>>
>>>>>> On 03/19/2015 09:50 AM, George Cherian wrote:
>>>>>>> Hi Robert,
>>>>>>>
>>>>>>> This looks like a extcon driver based on gpio for USB.
>>>>>>>
>>>>>>> Roger posted a generic one a while back.
>>>>>>> https://lkml.org/lkml/2015/2/2/187
>>>>>>>
>>>>>>> Doesn't this serve the purpose rather than adding this driver?
>>>>>>
>>>>>> Roger's driver doesn't support VBUS state detection so it cannot handle
>>>>> I feel Roger's driver could be extended for supporting VBUS.
>>>>> Also I think Roger's driver is about to get merged.
>>>>> Probably, Roger or Chanwoo can better tell that
>>>>
>>>> It is already queued for 4.1 and is available in linux-next.
>>>>
>>>>>
>>>>>> situation when USB cable is unpluged. In addition some of Odroid boards
>>>>>> has only VBUS detection (without ID pin), so this driver cannot handle
>>>>>> them at all.
>>>>
>>>> why not?
>>>>
>>>> x15-beagleboard also gets VBUS event over GPIO and I was planning to extent it
>>>> to support VBUS detection.
>>>
>>> Sounds good to me to extent extcon-usb-gpio.c.
>>> I'd like to hold only one extcon driver to support both USB and
>>> USB-HOST with gpio .
>>>
>>> There are one more extcon-gpio driver in mailing list as following:
>>> - extcon-usb-gpio.c (will be merged to Linux 4.1)
>>> - extcon-odroid-usbotg.c
>>> - extcon-otg_gpio.c [1]
>>> [1] https://lkml.org/lkml/2015/2/19/411
>>>
>>> The each extcon gpio driver support both USB/USB-HOST cable by using
>>> different way,
>>> Because some board which detect USB/USB-HOST by gpio have a little
>>> different pin composition
>>
>> These differences are small. In general we have three cases:
>>
>> 1. We have both VBUS and ID pin detection - we can detect USB, USB-HOST
>> and cable disconnection.
>>
>> 2. We have only VBUS detection - we can detect USB and cable disconnection.
>>
>> 3. We have ID pin only - we can distinguish between USB and USB-HOST but
>> without ability to detect cable disconnection.
>>
>>>
>>> I think only one extcon driver can support all cases with optional properties.
>>
>> So my driver in current form is ready for that. Only thing it would need
>> to change is to make VBUS detection an option (for now is mandatory
>> because all of supported Odroid boards have it). Then boards with VBUS
>> detection only or ID pin detection only will be handled also. I can also
>> change name of the driver to more generic. I'm going to prepare V2 on my
>> patches today.
> 
> Could you implement this feature on extcon-usb-gpio.c to support various pin composition?
> because extcon-usb-gpio.c was already implemented by Roger.
> If you implement other extcon driver to detect USB/USB-HOST cable by using gpio,
> there will be similar two extcon gpio driver for USB cable.
> 
> And,
> As Roger comment, he have the plan to extend the extcon-usb-gpio.c.
> So, If you will implement some feature for extcon driver with gpio,
> I'd like you to share your plan this thread to remove duplicat work.

extcon-usb-gpio.c supports case (3). (only ID pin)
I have plans to support case (1). (both ID and VBUS)

But Robert can go ahead and implement (2) and (1) over extcon-usb-gpio.c
if he wishes. The driver can easily decide which logic to follow depending on the
availability of the GPIO pins in the device tree.

cheers,
-roger


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

end of thread, other threads:[~2015-03-20  8:51 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-18 14:04 [RFC 00/19] dwc3: add USB OTG role switch support Robert Baldyga
2015-03-18 14:04 ` [RFC 01/19] extcon: add extcon-odroid-usbotg driver Robert Baldyga
2015-03-19  8:50   ` George Cherian
2015-03-19 12:07     ` Robert Baldyga
2015-03-19 12:19       ` George Cherian
2015-03-19 14:45         ` Roger Quadros
2015-03-19 20:50           ` Chanwoo Choi
2015-03-20  7:25             ` Robert Baldyga
2015-03-20  7:45               ` Chanwoo Choi
2015-03-20  8:51                 ` Roger Quadros
2015-03-18 14:04 ` [RFC 02/19] dt-bindings: extcon: Add doc for extcon-odroid-usbotg Robert Baldyga
2015-03-18 14:04 ` [RFC 03/19] ARM: dts: exynos5422-odroidxu3: add odroid-usbotg extcon support Robert Baldyga
2015-03-18 14:04 ` [RFC 04/19] dwc3: gadget: add VBUS session handling Robert Baldyga
2015-03-18 14:04 ` [RFC 05/19] dwc3: gadget: enable/disable ep0 in dwc3_gadget_run_stop() Robert Baldyga
2015-03-18 14:04 ` [RFC 06/19] dwc3: gadget: check returned value in suspend/resume Robert Baldyga
2015-03-18 14:04 ` [RFC 07/19] dwc3: core: cleanup suspend/resume code Robert Baldyga
2015-03-18 15:00   ` Sergei Shtylyov
2015-03-18 14:04 ` [RFC 08/19] dwc3: core: handle event buffers in core_init/exit Robert Baldyga
2015-03-18 14:04 ` [RFC 09/19] dwc3: core: make dwc3_core_init/exit non-static Robert Baldyga
2015-03-18 14:04 ` [RFC 10/19] dwc3: add missing OTG register definitions Robert Baldyga
2015-03-18 14:04 ` [RFC 11/19] dwc3: add OTG handling code Robert Baldyga
2015-03-19  7:38   ` George Cherian
2015-03-18 14:04 ` [RFC 12/19] dwc3: otg: add ext_otg_ops support Robert Baldyga
2015-03-18 14:04 ` [RFC 13/19] dwc3: gadget: register gadget in OTG core Robert Baldyga
2015-03-18 14:04 ` [RFC 14/19] dwc3: host: don't add XHCI device only if in OTG mode Robert Baldyga
2015-03-18 14:04 ` [RFC 15/19] dwc3: core: initialize OTG in DWC3 core Robert Baldyga
2015-03-18 14:04 ` [RFC 16/19] dwc3: exynos: add software role switching code Robert Baldyga
2015-03-18 14:04 ` [RFC 17/19] ARM: dts: exynos5420: set usb3_lpm_capable in dwc3 controllers Robert Baldyga
2015-03-18 14:04 ` [RFC 18/19] ARM: dts: exynos5420: add snps,dis_u3_susphy_quirk to " Robert Baldyga
2015-03-18 14:04 ` [RFC 19/19] ARM: dts: exynos5422-odroidxu3: make usbdrd3 extcon client Robert Baldyga
2015-03-19  2:33 ` [RFC 00/19] dwc3: add USB OTG role switch support Chanwoo Choi
2015-03-19  8:27   ` Robert Baldyga

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).