linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v17 0/3] USB Type-C Connector class
@ 2017-02-21 14:24 Heikki Krogerus
  2017-02-21 14:24 ` [PATCH v17 1/3] lib/string: add sysfs_match_string helper Heikki Krogerus
                   ` (4 more replies)
  0 siblings, 5 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-02-21 14:24 UTC (permalink / raw)
  To: Greg KH
  Cc: Guenter Roeck, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

The USB Type-C class is meant to provide unified interface to the
userspace to present the USB Type-C ports in a system.

Changes since v16:
- Using PTR_ERR_OR_ZERO macro in typec_init().

Changes since v15:
- "stingification" as proposed by Felipe
- Checking ARRAY_SIZE in supported_accessory_modes() as proposed by Guenter

Changes since v14:
- Fixes proposed by Mika
- "identity" directory for all discover identity VDOs instead of "vdo" attribute
- alternate mode device names to just "svid-<svid>"

Changes since v13:
- New API. Everything is registered separately.

Changes since v12:
- Added prefer_role member to typec_capability structure as requested by Guenter

Changes since v11:
- The port drivers are responsible of removing the alternate
  modes (just like the documentation already said).

Changes since v10:
- Using ATTRIBUTE_GROUPS and DEVICE_ATTR marcos everywhere
- Moved sysfs_match_string to lib/string.c
- Rationalized uevents
- Calling ida_destroy

Changes since v9:
- Minor typec_wcove.c cleanup as proposed by Guenter Roeck. No
  function affect.

Changes since v8:
- checking sysfs_streq() result correctly in sysfs_strmatch
- fixed accessory check in supported_accessory_mode
- using "none" as the only string that can clear the preferred role

Changes since v7:
- Removed "type" attribute from partners
- Added supports_usb_power_delivery attribute for partner and cable

Changes since v6:
- current_vconn_role attr renamed to vconn_source (no API changes)
- Small documentation improvements proposed by Vincent Palatin

Changes since v5:
- Only updating the roles based on driver notifications
- Added MODULE_ALIAS for the WhiskeyCove module
- Including the patch that creates the actual platform device for the
  WhiskeyCove Type-C PHY in this series.

Changes since v4:
- Remove the port lock completely

Changes since v3:
- Documentation cleanup as proposed by Roger Quadros
- Setting partner altmodes member to NULL on removal and fixing a
  warning, as proposed by Guenter Roeck
- Added the following attributes for partners and cables:
  * supports_usb_power_delivery
  * id_header_vdo
- "id_header_vdo" is visible only when the partner or cable supports
  USB Power Delivery communication.
- Partner attribute "accessory" is hidden when the partner type is not
  "Accessory".

Changes since v2:
- Notification on role and alternate mode changes
- cleanups

Changes since v1:
- Completely rewrote alternate mode support
- Patners, cables and cable plugs presented as devices.


Heikki Krogerus (3):
  lib/string: add sysfs_match_string helper
  usb: USB Type-C connector class
  usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY

 Documentation/ABI/testing/sysfs-class-typec |  276 ++++++
 Documentation/usb/typec.rst                 |  185 ++++
 MAINTAINERS                                 |    9 +
 drivers/usb/Kconfig                         |    2 +
 drivers/usb/Makefile                        |    2 +
 drivers/usb/typec/Kconfig                   |   22 +
 drivers/usb/typec/Makefile                  |    2 +
 drivers/usb/typec/typec.c                   | 1262 +++++++++++++++++++++++++++
 drivers/usb/typec/typec_wcove.c             |  377 ++++++++
 include/linux/string.h                      |   10 +
 include/linux/usb/typec.h                   |  243 ++++++
 lib/string.c                                |   26 +
 12 files changed, 2416 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-typec
 create mode 100644 Documentation/usb/typec.rst
 create mode 100644 drivers/usb/typec/Kconfig
 create mode 100644 drivers/usb/typec/Makefile
 create mode 100644 drivers/usb/typec/typec.c
 create mode 100644 drivers/usb/typec/typec_wcove.c
 create mode 100644 include/linux/usb/typec.h

-- 
2.11.0

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

* [PATCH v17 1/3] lib/string: add sysfs_match_string helper
  2017-02-21 14:24 [PATCH v17 0/3] USB Type-C Connector class Heikki Krogerus
@ 2017-02-21 14:24 ` Heikki Krogerus
  2017-02-21 14:24 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-02-21 14:24 UTC (permalink / raw)
  To: Greg KH
  Cc: Guenter Roeck, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

Make a simple helper for matching strings with sysfs
attribute files. In most parts the same as match_string(),
except sysfs_match_string() uses sysfs_streq() instead of
strcmp() for matching. This is more convenient when used
with sysfs attributes.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Tested-by: Guenter Roeck <linux@roeck-us.net>
---
 include/linux/string.h | 10 ++++++++++
 lib/string.c           | 26 ++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 040eab355533..96e4ad598210 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -136,6 +136,16 @@ static inline int strtobool(const char *s, bool *res)
 }
 
 int match_string(const char * const *array, size_t n, const char *string);
+int __sysfs_match_string(const char * const *array, size_t n, const char *s);
+
+/**
+ * sysfs_match_string - matches given string in an array
+ * @_a: array of strings
+ * @_s: string to match with
+ *
+ * Helper for __sysfs_match_string(). Calculates the size of @a automatically.
+ */
+#define sysfs_match_string(_a, _s) __sysfs_match_string(_a, ARRAY_SIZE(_a), _s)
 
 #ifdef CONFIG_BINARY_PRINTF
 int vbin_printf(u32 *bin_buf, size_t size, const char *fmt,
diff --git a/lib/string.c b/lib/string.c
index b3c22a285a78..f47a72098c87 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -656,6 +656,32 @@ int match_string(const char * const *array, size_t n, const char *string)
 }
 EXPORT_SYMBOL(match_string);
 
+/**
+ * __sysfs_match_string - matches given string in an array
+ * @array: array of strings
+ * @n: number of strings in the array or -1 for NULL terminated arrays
+ * @str: string to match with
+ *
+ * Returns index of @str in the @array or -EINVAL, just like match_string().
+ * Uses sysfs_streq instead of strcmp for matching.
+ */
+int __sysfs_match_string(const char * const *array, size_t n, const char *str)
+{
+	const char *item;
+	int index;
+
+	for (index = 0; index < n; index++) {
+		item = array[index];
+		if (!item)
+			break;
+		if (sysfs_streq(item, str))
+			return index;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(__sysfs_match_string);
+
 #ifndef __HAVE_ARCH_MEMSET
 /**
  * memset - Fill a region of memory with the given value
-- 
2.11.0

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

* [PATCH v17 2/3] usb: USB Type-C connector class
  2017-02-21 14:24 [PATCH v17 0/3] USB Type-C Connector class Heikki Krogerus
  2017-02-21 14:24 ` [PATCH v17 1/3] lib/string: add sysfs_match_string helper Heikki Krogerus
@ 2017-02-21 14:24 ` Heikki Krogerus
  2017-03-02 15:22   ` Mats Karrman
  2017-03-03  3:35   ` Peter Chen
  2017-02-21 14:24 ` [PATCH v17 3/3] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY Heikki Krogerus
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-02-21 14:24 UTC (permalink / raw)
  To: Greg KH
  Cc: Guenter Roeck, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

The purpose of USB Type-C connector class is to provide
unified interface for the user space to get the status and
basic information about USB Type-C connectors on a system,
control over data role swapping, and when the port supports
USB Power Delivery, also control over power role swapping
and Alternate Modes.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Tested-by: Guenter Roeck <linux@roeck-us.net>
---
 Documentation/ABI/testing/sysfs-class-typec |  276 ++++++
 Documentation/usb/typec.rst                 |  185 ++++
 MAINTAINERS                                 |    9 +
 drivers/usb/Kconfig                         |    2 +
 drivers/usb/Makefile                        |    2 +
 drivers/usb/typec/Kconfig                   |    7 +
 drivers/usb/typec/Makefile                  |    1 +
 drivers/usb/typec/typec.c                   | 1262 +++++++++++++++++++++++++++
 include/linux/usb/typec.h                   |  243 ++++++
 9 files changed, 1987 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-typec
 create mode 100644 Documentation/usb/typec.rst
 create mode 100644 drivers/usb/typec/Kconfig
 create mode 100644 drivers/usb/typec/Makefile
 create mode 100644 drivers/usb/typec/typec.c
 create mode 100644 include/linux/usb/typec.h

diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec
new file mode 100644
index 000000000000..3819fd9a5731
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-typec
@@ -0,0 +1,276 @@
+USB Type-C port devices (eg. /sys/class/typec/port0/)
+
+What:		/sys/class/typec/<port>/data_role
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		The supported USB data roles. This attribute can be used for
+		requesting data role swapping on the port. Swapping is supported
+		as synchronous operation, so write(2) to the attribute will not
+		return until the operation has finished. The attribute is
+		notified about role changes so that poll(2) on the attribute
+		wakes up. Change on the role will also generate uevent
+		KOBJ_CHANGE on the port. The current role is show in brackets,
+		for example "[host] device" when DRP port is in host mode.
+
+		Valid values: host, device
+
+What:		/sys/class/typec/<port>/power_role
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		The supported power roles. This attribute can be used to request
+		power role swap on the port when the port supports USB Power
+		Delivery. Swapping is supported as synchronous operation, so
+		write(2) to the attribute will not return until the operation
+		has finished. The attribute is notified about role changes so
+		that poll(2) on the attribute wakes up. Change on the role will
+		also generate uevent KOBJ_CHANGE. The current role is show in
+		brackets, for example "[source] sink" when in source mode.
+
+		Valid values: source, sink
+
+What:		/sys/class/typec/<port>/vconn_source
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows is the port VCONN Source. This attribute can be used to
+		request VCONN swap to change the VCONN Source during connection
+		when both the port and the partner support USB Power Delivery.
+		Swapping is supported as synchronous operation, so write(2) to
+		the attribute will not return until the operation has finished.
+		The attribute is notified about VCONN source changes so that
+		poll(2) on the attribute wakes up. Change on VCONN source also
+		generates uevent KOBJ_CHANGE.
+
+		Valid values:
+		- "no" when the port is not the VCONN Source
+		- "yes" when the port is the VCONN Source
+
+What:		/sys/class/typec/<port>/power_operation_mode
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows the current power operational mode the port is in. The
+		power operation mode means current level for VBUS. In case USB
+		Power Delivery communication is used for negotiating the levels,
+		power operation mode should show "usb_power_delivery".
+
+		Valid values:
+		- default
+		- 1.5A
+		- 3.0A
+		- usb_power_delivery
+
+What:		/sys/class/typec/<port>/preferred_role
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		The user space can notify the driver about the preferred role.
+		It should be handled as enabling of Try.SRC or Try.SNK, as
+		defined in USB Type-C specification, in the port drivers. By
+		default the preferred role should come from the platform.
+
+		Valid values: source, sink, none (to remove preference)
+
+What:		/sys/class/typec/<port>/supported_accessory_modes
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Space separated list of accessory modes, defined in the USB
+		Type-C specification, the port supports.
+
+What:		/sys/class/typec/<port>/usb_power_delivery_revision
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Revision number of the supported USB Power Delivery
+		specification, or 0 when USB Power Delivery is not supported.
+
+What:		/sys/class/typec/<port>/usb_typec_revision
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Revision number of the supported USB Type-C specification.
+
+
+USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)
+
+What:		/sys/class/typec/<port>-partner/accessory_mode
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows the Accessory Mode name when the partner is an Accessory.
+		The Accessory Modes are defined in USB Type-C Specification.
+
+What:		/sys/class/typec/<port>-partner/supports_usb_power_delivery
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows if the partner supports USB Power Delivery communication:
+		Valid values: yes, no
+
+What:		/sys/class/typec/<port>-partner>/identity/
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		This directory appears only if the port device driver is capable
+		of showing the result of Discover Identity USB power delivery
+		command. That will not always be possible even when USB power
+		delivery is supported, for example when USB power delivery
+		communication for the port is mostly handled in firmware. If the
+		directory exists, it will have an attribute file for every VDO
+		in Discover Identity command result.
+
+What:		/sys/class/typec/<port>-partner/identity/id_header
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		ID Header VDO part of Discover Identity command result. The
+		value will show 0 until Discover Identity command result becomes
+		available. The value can be polled.
+
+What:		/sys/class/typec/<port>-partner/identity/cert_stat
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Cert Stat VDO part of Discover Identity command result. The
+		value will show 0 until Discover Identity command result becomes
+		available. The value can be polled.
+
+What:		/sys/class/typec/<port>-partner/identity/product
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Product VDO part of Discover Identity command result. The value
+		will show 0 until Discover Identity command result becomes
+		available. The value can be polled.
+
+
+USB Type-C cable devices (eg. /sys/class/typec/port0-cable/)
+
+Note: Electronically Marked Cables will have a device also for one cable plug
+(eg. /sys/class/typec/port0-plug0). If the cable is active and has also SOP
+Double Prime controller (USB Power Deliver specification ch. 2.4) it will have
+second device also for the other plug. Both plugs may have alternate modes as
+described in USB Type-C and USB Power Delivery specifications.
+
+What:		/sys/class/typec/<port>-cable/type
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows if the cable is active.
+		Valid values: active, passive
+
+What:		/sys/class/typec/<port>-cable/plug_type
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows type of the plug on the cable:
+		- type-a - Standard A
+		- type-b - Standard B
+		- type-c
+		- captive
+
+What:		/sys/class/typec/<port>-cable/identity/
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		This directory appears only if the port device driver is capable
+		of showing the result of Discover Identity USB power delivery
+		command. That will not always be possible even when USB power
+		delivery is supported. If the directory exists, it will have an
+		attribute for every VDO returned by Discover Identity command.
+
+What:		/sys/class/typec/<port>-cable/identity/id_header
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		ID Header VDO part of Discover Identity command result. The
+		value will show 0 until Discover Identity command result becomes
+		available. The value can be polled.
+
+What:		/sys/class/typec/<port>-cable/identity/cert_stat
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Cert Stat VDO part of Discover Identity command result. The
+		value will show 0 until Discover Identity command result becomes
+		available. The value can be polled.
+
+What:		/sys/class/typec/<port>-cable/identity/product
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Product VDO part of Discover Identity command result. The value
+		will show 0 until Discover Identity command result becomes
+		available. The value can be polled.
+
+
+Alternate Mode devices.
+
+The alternate modes will have Standard or Vendor ID (SVID) assigned by USB-IF.
+The ports, partners and cable plugs can have alternate modes. A supported SVID
+will consist of a set of modes. Every SVID a port/partner/plug supports will
+have a device created for it, and every supported mode for a supported SVID will
+have its own directory under that device. Below <dev> refers to the device for
+the alternate mode.
+
+What:		/sys/class/typec/<port|partner|cable>/<dev>/svid
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		The SVID (Standard or Vendor ID) assigned by USB-IF for this
+		alternate mode.
+
+What:		/sys/class/typec/<port|partner|cable>/<dev>/mode<index>/
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Every supported mode will have its own directory. The name of
+		a mode will be "mode<index>" (for example mode1), where <index>
+		is the actual index to the mode VDO returned by Discover Modes
+		USB power delivery command.
+
+What:		/sys/class/typec/<port|partner|cable>/<dev>/mode<index>/description
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows description of the mode. The description is optional for
+		the drivers, just like with the Billboard Devices.
+
+What:		/sys/class/typec/<port|partner|cable>/<dev>/mode<index>/vdo
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows the VDO in hexadecimal returned by Discover Modes command
+		for this mode.
+
+What:		/sys/class/typec/<port|partner|cable>/<dev>/mode<index>/active
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Shows if the mode is active or not. The attribute can be used
+		for entering/exiting the mode with partners and cable plugs, and
+		with the port alternate modes it can be used for disabling
+		support for specific alternate modes. Entering/exiting modes is
+		supported as synchronous operation so write(2) to the attribute
+		does not return until the enter/exit mode operation has
+		finished. The attribute is notified when the mode is
+		entered/exited so poll(2) on the attribute wakes up.
+		Entering/exiting a mode will also generate uevent KOBJ_CHANGE.
+
+		Valid values: yes, no
+
+What:		/sys/class/typec/<port>/<dev>/mode<index>/supported_roles
+Date:		March 2017
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Space separated list of the supported roles.
+
+		This attribute is available for the devices describing the
+		alternate modes a port supports, and it will not be exposed with
+		the devices presenting the alternate modes the partners or cable
+		plugs support.
+
+		Valid values: source, sink
diff --git a/Documentation/usb/typec.rst b/Documentation/usb/typec.rst
new file mode 100644
index 000000000000..e9b4ad4c3baa
--- /dev/null
+++ b/Documentation/usb/typec.rst
@@ -0,0 +1,185 @@
+
+USB Type-C connector class
+==========================
+
+Introduction
+------------
+
+The typec class is meant for describing the USB Type-C ports in a system to the
+user space in unified fashion. The class is designed to provide nothing else
+except the user space interface implementation in hope that it can be utilized
+on as many platforms as possible.
+
+The platforms are expected to register every USB Type-C port they have with the
+class. In a normal case the registration will be done by a USB Type-C or PD PHY
+driver, but it may be a driver for firmware interface such as UCSI, driver for
+USB PD controller or even driver for Thunderbolt3 controller. This document
+considers the component registering the USB Type-C ports with the class as "port
+driver".
+
+On top of showing the capabilities, the class also offer user space control over
+the roles and alternate modes of ports, partners and cable plugs when the port
+driver is capable of supporting those features.
+
+The class provides an API for the port drivers described in this document. The
+attributes are described in Documentation/ABI/testing/sysfs-class-typec.
+
+User space interface
+--------------------
+Every port will be presented as its own device under /sys/class/typec/. The
+first port will be named "port0", the second "port1" and so on.
+
+When connected, the partner will be presented also as its own device under
+/sys/class/typec/. The parent of the partner device will always be the port it
+is attached to. The partner attached to port "port0" will be named
+"port0-partner". Full path to the device would be
+/sys/class/typec/port0/port0-partner/.
+
+The cable and the two plugs on it may also be optionally presented as their own
+devices under /sys/class/typec/. The cable attached to the port "port0" port
+will be named port0-cable and the plug on the SOP Prime end (see USB Power
+Delivery Specification ch. 2.4) will be named "port0-plug0" and on the SOP
+Double Prime end "port0-plug1". The parent of a cable will always be the port,
+and the parent of the cable plugs will always be the cable.
+
+If the port, partner or cable plug support Alternate Modes, every supported
+Alternate Mode SVID will have their own device describing them. The Alternate
+Modes will not be attached to the typec class. The parent of an alternate mode
+will be the device that supports it, so for example an alternate mode of
+port0-partner will bees presented under /sys/class/typec/port0-partner/. Every
+mode that is supported will have its own group under the Alternate Mode device
+named "mode<index>", for example /sys/class/typec/port0/<alternate mode>/mode1/.
+The requests for entering/exiting a mode can be done with "active" attribute
+file in that group.
+
+Driver API
+----------
+
+Registering the ports
+~~~~~~~~~~~~~~~~~~~~~
+
+The port drivers will describe every Type-C port they control with struct
+typec_capability data structure, and register them with the following API:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_register_port typec_unregister_port
+
+When registering the ports, the prefer_role member in struct typec_capability
+deserves special notice. If the port that is being registered does not have
+initial role preference, which means the port does not execute Try.SNK or
+Try.SRC by default, the member must have value TYPEC_NO_PREFERRED_ROLE.
+Otherwise if the port executes Try.SNK by default the member must have value
+TYPEC_DEVICE and with Try.SRC the value must be TYPEC_HOST.
+
+Registering Partners
+~~~~~~~~~~~~~~~~~~~~
+
+After successful connection of a partner, the port driver needs to register the
+partner with the class. Details about the partner need to be described in struct
+typec_partner_desc. The class copies the details of the partner during
+registration. The class offers the following API for registering/unregistering
+partners.
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_register_partner typec_unregister_partner
+
+The class will provide a handle to struct typec_partner if the registration was
+successful, or NULL.
+
+If the partner is USB Power Delivery capable, and the port driver is able to
+show the result of Discover Identity command, the partner descriptor structure
+should include handle to struct usb_pd_identity instance. The class will then
+create a sysfs directory for the identity under the partner device. The result
+of Discover Identity command can then be reported with the following API:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_partner_set_identity
+
+Registering Cables
+~~~~~~~~~~~~~~~~~~
+
+After successful connection of a cable that supports USB Power Delivery
+Structured VDM "Discover Identity", the port driver needs to register the cable
+and one or two plugs, depending if there is CC Double Prime controller present
+in the cable or not. So a cable capable of SOP Prime communication, but not SOP
+Double Prime communication, should only have one plug registered. For more
+information about SOP communication, please read chapter about it from the
+latest USB Power Delivery specification.
+
+The plugs are represented as their own devices. The cable is registered first,
+followed by registration of the cable plugs. The cable will be the parent device
+for the plugs. Details about the cable need to be described in struct
+typec_cable_desc and about a plug in struct typec_plug_desc. The class copies
+the details during registration. The class offers the following API for
+registering/unregistering cables and their plugs:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_register_cable typec_unregister_cable typec_register_plug
+   typec_unregister_plug
+
+The class will provide a handle to struct typec_cable and struct typec_plug if
+the registration is successful, or NULL if it isn't.
+
+If the cable is USB Power Delivery capable, and the port driver is able to show
+the result of Discover Identity command, the cable descriptor structure should
+include handle to struct usb_pd_identity instance. The class will then create a
+sysfs directory for the identity under the cable device. The result of Discover
+Identity command can then be reported with the following API:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_cable_set_identity
+
+Notifications
+~~~~~~~~~~~~~
+
+When the partner has executed a role change, or when the default roles change
+during connection of a partner or cable, the port driver must use the following
+APIs to report it to the class:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_set_data_role typec_set_pwr_role typec_set_vconn_role
+   typec_set_pwr_opmode
+
+Alternate Modes
+~~~~~~~~~~~~~~~
+
+USB Type-C Ports, Partners and Cable Plugs may support Alternate Modes with USB
+Type-C. Each Alternate Mode will have SVID, which is either a Standard ID given
+by USB-IF or vendor ID. Each supported SVID can have 1 - 6 modes. The class
+provides struct typec_mode_desc for describing individual mode of a SVID, and
+struct typec_altmode_desc which is a container of all the modes of a SVID that a
+port, partner or cable plug supports.
+
+Ports that support Alternate Modes need to register each SVID they support with
+the following API:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_port_register_altmode
+
+If a partner or cable plug provides a list of SVIDs as response to USB Power
+Delivery Structured VDM Discover SVIDs message, each SVID needs to be
+registered.
+
+API for the partners:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_partner_register_altmode
+
+API for the Cable Plugs:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_plug_register_altmode
+
+So ports, partners and cable plugs will register the alternate modes with their
+own functions, but the registration will always return a handle to struct
+typec_altmode on success, or NULL. The unregistration will happen with the same
+function:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_unregister_altmode
+
+If a partner or cable plug enters or exits a mode, the port driver needs to
+notify the class with the following API:
+
+.. kernel-doc:: drivers/usb/typec/typec.c
+   :functions: typec_altmode_update_active
diff --git a/MAINTAINERS b/MAINTAINERS
index 277c2e2062bd..88824ca9cf4d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13100,6 +13100,15 @@ F:	drivers/usb/
 F:	include/linux/usb.h
 F:	include/linux/usb/
 
+USB TYPEC SUBSYSTEM
+M:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+L:	linux-usb@vger.kernel.org
+S:	Maintained
+F:	Documentation/ABI/testing/sysfs-class-typec
+F:	Documentation/usb/typec.rst
+F:	drivers/usb/typec/
+F:	include/linux/usb/typec.h
+
 USB UHCI DRIVER
 M:	Alan Stern <stern@rowland.harvard.edu>
 L:	linux-usb@vger.kernel.org
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index fbe493d44e81..89c322e0742b 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -152,6 +152,8 @@ source "drivers/usb/phy/Kconfig"
 
 source "drivers/usb/gadget/Kconfig"
 
+source "drivers/usb/typec/Kconfig"
+
 config USB_LED_TRIG
 	bool "USB LED Triggers"
 	depends on LEDS_CLASS && LEDS_TRIGGERS
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 7791af6c102c..c7f409885eff 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -62,3 +62,5 @@ obj-$(CONFIG_USB_GADGET)	+= gadget/
 obj-$(CONFIG_USB_COMMON)	+= common/
 
 obj-$(CONFIG_USBIP_CORE)	+= usbip/
+
+obj-$(CONFIG_TYPEC)		+= typec/
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
new file mode 100644
index 000000000000..17792f9114c6
--- /dev/null
+++ b/drivers/usb/typec/Kconfig
@@ -0,0 +1,7 @@
+
+menu "USB Power Delivery and Type-C drivers"
+
+config TYPEC
+	tristate
+
+endmenu
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
new file mode 100644
index 000000000000..1012a8bed6d5
--- /dev/null
+++ b/drivers/usb/typec/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TYPEC)		+= typec.o
diff --git a/drivers/usb/typec/typec.c b/drivers/usb/typec/typec.c
new file mode 100644
index 000000000000..89e540bb7ff3
--- /dev/null
+++ b/drivers/usb/typec/typec.c
@@ -0,0 +1,1262 @@
+/*
+ * USB Type-C Connector Class
+ *
+ * Copyright (C) 2017, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.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 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb/typec.h>
+
+struct typec_mode {
+	int				index;
+	u32				vdo;
+	char				*desc;
+	enum typec_port_type		roles;
+
+	struct typec_altmode		*alt_mode;
+
+	unsigned int			active:1;
+
+	char				group_name[6];
+	struct attribute_group		group;
+	struct attribute		*attrs[5];
+	struct device_attribute		vdo_attr;
+	struct device_attribute		desc_attr;
+	struct device_attribute		active_attr;
+	struct device_attribute		roles_attr;
+};
+
+struct typec_altmode {
+	struct device			dev;
+	u16				svid;
+	int				n_modes;
+	struct typec_mode		modes[ALTMODE_MAX_MODES];
+	const struct attribute_group	*mode_groups[ALTMODE_MAX_MODES];
+};
+
+struct typec_plug {
+	struct device			dev;
+	enum typec_plug_index		index;
+};
+
+struct typec_cable {
+	struct device			dev;
+	enum typec_plug_type		type;
+	struct usb_pd_identity		*identity;
+	unsigned int			active:1;
+};
+
+struct typec_partner {
+	struct device			dev;
+	unsigned int			usb_pd:1;
+	struct usb_pd_identity		*identity;
+	enum typec_accessory		accessory;
+};
+
+struct typec_port {
+	unsigned int			id;
+	struct device			dev;
+
+	int				prefer_role;
+	enum typec_data_role		data_role;
+	enum typec_role			pwr_role;
+	enum typec_role			vconn_role;
+	enum typec_pwr_opmode		pwr_opmode;
+
+	const struct typec_capability	*cap;
+};
+
+#define to_typec_port(_dev_) container_of(_dev_, struct typec_port, dev)
+#define to_typec_plug(_dev_) container_of(_dev_, struct typec_plug, dev)
+#define to_typec_cable(_dev_) container_of(_dev_, struct typec_cable, dev)
+#define to_typec_partner(_dev_) container_of(_dev_, struct typec_partner, dev)
+#define to_altmode(_dev_) container_of(_dev_, struct typec_altmode, dev)
+
+static const struct device_type typec_partner_dev_type;
+static const struct device_type typec_cable_dev_type;
+static const struct device_type typec_plug_dev_type;
+static const struct device_type typec_port_dev_type;
+
+#define is_typec_partner(_dev_) (_dev_->type == &typec_partner_dev_type)
+#define is_typec_cable(_dev_) (_dev_->type == &typec_cable_dev_type)
+#define is_typec_plug(_dev_) (_dev_->type == &typec_plug_dev_type)
+#define is_typec_port(_dev_) (_dev_->type == &typec_port_dev_type)
+
+static DEFINE_IDA(typec_index_ida);
+static struct class *typec_class;
+
+/* Common attributes */
+
+static const char * const typec_accessory_modes[] = {
+	[TYPEC_ACCESSORY_NONE]		= "none",
+	[TYPEC_ACCESSORY_AUDIO]		= "analog_audio",
+	[TYPEC_ACCESSORY_DEBUG]		= "debug",
+};
+
+static struct usb_pd_identity *get_pd_identity(struct device *dev)
+{
+	if (is_typec_partner(dev)) {
+		struct typec_partner *partner = to_typec_partner(dev);
+
+		return partner->identity;
+	} else if (is_typec_cable(dev)) {
+		struct typec_cable *cable = to_typec_cable(dev);
+
+		return cable->identity;
+	}
+	return NULL;
+}
+
+static ssize_t id_header_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct usb_pd_identity *id = get_pd_identity(dev);
+
+	return sprintf(buf, "0x%08x\n", id->id_header);
+}
+static DEVICE_ATTR_RO(id_header);
+
+static ssize_t cert_stat_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct usb_pd_identity *id = get_pd_identity(dev);
+
+	return sprintf(buf, "0x%08x\n", id->cert_stat);
+}
+static DEVICE_ATTR_RO(cert_stat);
+
+static ssize_t product_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct usb_pd_identity *id = get_pd_identity(dev);
+
+	return sprintf(buf, "0x%08x\n", id->product);
+}
+static DEVICE_ATTR_RO(product);
+
+static struct attribute *usb_pd_id_attrs[] = {
+	&dev_attr_id_header.attr,
+	&dev_attr_cert_stat.attr,
+	&dev_attr_product.attr,
+	NULL
+};
+
+static const struct attribute_group usb_pd_id_group = {
+	.name = "identity",
+	.attrs = usb_pd_id_attrs,
+};
+
+static const struct attribute_group *usb_pd_id_groups[] = {
+	&usb_pd_id_group,
+	NULL,
+};
+
+static void typec_report_identity(struct device *dev)
+{
+	sysfs_notify(&dev->kobj, "identity", "id_header");
+	sysfs_notify(&dev->kobj, "identity", "cert_stat");
+	sysfs_notify(&dev->kobj, "identity", "product");
+}
+
+/* ------------------------------------------------------------------------- */
+/* Alternate Modes */
+
+/**
+ * typec_altmode_update_active - Report Enter/Exit mode
+ * @alt: Handle to the alternate mode
+ * @mode: Mode index
+ * @active: True when the mode has been entered
+ *
+ * If a partner or cable plug executes Enter/Exit Mode command successfully, the
+ * drivers use this routine to report the updated state of the mode.
+ */
+void typec_altmode_update_active(struct typec_altmode *alt, int mode,
+				 bool active)
+{
+	struct typec_mode *m = &alt->modes[mode];
+	char dir[6];
+
+	if (m->active == active)
+		return;
+
+	m->active = active;
+	snprintf(dir, sizeof(dir), "mode%d", mode);
+	sysfs_notify(&alt->dev.kobj, dir, "active");
+	kobject_uevent(&alt->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_altmode_update_active);
+
+/**
+ * typec_altmode2port - Alternate Mode to USB Type-C port
+ * @alt: The Alternate Mode
+ *
+ * Returns handle to the port that a cable plug or partner with @alt is
+ * connected to.
+ */
+struct typec_port *typec_altmode2port(struct typec_altmode *alt)
+{
+	if (is_typec_plug(alt->dev.parent))
+		return to_typec_port(alt->dev.parent->parent->parent);
+	if (is_typec_partner(alt->dev.parent))
+		return to_typec_port(alt->dev.parent->parent);
+	if (is_typec_port(alt->dev.parent))
+		return to_typec_port(alt->dev.parent);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(typec_altmode2port);
+
+static ssize_t
+typec_altmode_vdo_show(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       vdo_attr);
+
+	return sprintf(buf, "0x%08x\n", mode->vdo);
+}
+
+static ssize_t
+typec_altmode_desc_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       desc_attr);
+
+	return sprintf(buf, "%s\n", mode->desc ? mode->desc : "");
+}
+
+static ssize_t
+typec_altmode_active_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       active_attr);
+
+	return sprintf(buf, "%s\n", mode->active ? "yes" : "no");
+}
+
+static ssize_t
+typec_altmode_active_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       active_attr);
+	struct typec_port *port = typec_altmode2port(mode->alt_mode);
+	bool activate;
+	int ret;
+
+	if (!port->cap->activate_mode)
+		return -EOPNOTSUPP;
+
+	ret = kstrtobool(buf, &activate);
+	if (ret)
+		return ret;
+
+	ret = port->cap->activate_mode(port->cap, mode->index, activate);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t
+typec_altmode_roles_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct typec_mode *mode = container_of(attr, struct typec_mode,
+					       roles_attr);
+	ssize_t ret;
+
+	switch (mode->roles) {
+	case TYPEC_PORT_DFP:
+		ret = sprintf(buf, "source\n");
+		break;
+	case TYPEC_PORT_UFP:
+		ret = sprintf(buf, "sink\n");
+		break;
+	case TYPEC_PORT_DRP:
+	default:
+		ret = sprintf(buf, "source sink\n");
+		break;
+	}
+	return ret;
+}
+
+static void typec_init_modes(struct typec_altmode *alt,
+			     struct typec_mode_desc *desc, bool is_port)
+{
+	int i;
+
+	for (i = 0; i < alt->n_modes; i++, desc++) {
+		struct typec_mode *mode = &alt->modes[i];
+
+		/* Not considering the human readable description critical */
+		mode->desc = kstrdup(desc->desc, GFP_KERNEL);
+		if (desc->desc && !mode->desc)
+			dev_err(&alt->dev, "failed to copy mode%d desc\n", i);
+
+		mode->alt_mode = alt;
+		mode->vdo = desc->vdo;
+		mode->roles = desc->roles;
+		mode->index = desc->index;
+		sprintf(mode->group_name, "mode%d", desc->index);
+
+		sysfs_attr_init(&mode->vdo_attr.attr);
+		mode->vdo_attr.attr.name = "vdo";
+		mode->vdo_attr.attr.mode = 0444;
+		mode->vdo_attr.show = typec_altmode_vdo_show;
+
+		sysfs_attr_init(&mode->desc_attr.attr);
+		mode->desc_attr.attr.name = "description";
+		mode->desc_attr.attr.mode = 0444;
+		mode->desc_attr.show = typec_altmode_desc_show;
+
+		sysfs_attr_init(&mode->active_attr.attr);
+		mode->active_attr.attr.name = "active";
+		mode->active_attr.attr.mode = 0644;
+		mode->active_attr.show = typec_altmode_active_show;
+		mode->active_attr.store = typec_altmode_active_store;
+
+		mode->attrs[0] = &mode->vdo_attr.attr;
+		mode->attrs[1] = &mode->desc_attr.attr;
+		mode->attrs[2] = &mode->active_attr.attr;
+
+		/* With ports, list the roles that the mode is supported with */
+		if (is_port) {
+			sysfs_attr_init(&mode->roles_attr.attr);
+			mode->roles_attr.attr.name = "supported_roles";
+			mode->roles_attr.attr.mode = 0444;
+			mode->roles_attr.show = typec_altmode_roles_show;
+
+			mode->attrs[3] = &mode->roles_attr.attr;
+		}
+
+		mode->group.attrs = mode->attrs;
+		mode->group.name = mode->group_name;
+
+		alt->mode_groups[i] = &mode->group;
+	}
+}
+
+static ssize_t svid_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct typec_altmode *alt = to_altmode(dev);
+
+	return sprintf(buf, "%04x\n", alt->svid);
+}
+static DEVICE_ATTR_RO(svid);
+
+static struct attribute *typec_altmode_attrs[] = {
+	&dev_attr_svid.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(typec_altmode);
+
+static void typec_altmode_release(struct device *dev)
+{
+	struct typec_altmode *alt = to_altmode(dev);
+	int i;
+
+	for (i = 0; i < alt->n_modes; i++)
+		kfree(alt->modes[i].desc);
+	kfree(alt);
+}
+
+static const struct device_type typec_altmode_dev_type = {
+	.name = "typec_alternate_mode",
+	.groups = typec_altmode_groups,
+	.release = typec_altmode_release,
+};
+
+static struct typec_altmode *
+typec_register_altmode(struct device *parent, struct typec_altmode_desc *desc)
+{
+	struct typec_altmode *alt;
+	int ret;
+
+	alt = kzalloc(sizeof(*alt), GFP_KERNEL);
+	if (!alt)
+		return NULL;
+
+	alt->svid = desc->svid;
+	alt->n_modes = desc->n_modes;
+	typec_init_modes(alt, desc->modes, is_typec_port(parent));
+
+	alt->dev.parent = parent;
+	alt->dev.groups = alt->mode_groups;
+	alt->dev.type = &typec_altmode_dev_type;
+	dev_set_name(&alt->dev, "svid-%04x", alt->svid);
+
+	ret = device_register(&alt->dev);
+	if (ret) {
+		dev_err(parent, "failed to register alternate mode (%d)\n",
+			ret);
+		put_device(&alt->dev);
+		return NULL;
+	}
+
+	return alt;
+}
+
+/**
+ * typec_unregister_altmode - Unregister Alternate Mode
+ * @alt: The alternate mode to be unregistered
+ *
+ * Unregister device created with typec_partner_register_altmode(),
+ * typec_plug_register_altmode() or typec_port_register_altmode().
+ */
+void typec_unregister_altmode(struct typec_altmode *alt)
+{
+	if (alt)
+		device_unregister(&alt->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_altmode);
+
+/* ------------------------------------------------------------------------- */
+/* Type-C Partners */
+
+static ssize_t accessory_mode_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct typec_partner *p = to_typec_partner(dev);
+
+	return sprintf(buf, "%s\n", typec_accessory_modes[p->accessory]);
+}
+static DEVICE_ATTR_RO(accessory_mode);
+
+static ssize_t supports_usb_power_delivery_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct typec_partner *p = to_typec_partner(dev);
+
+	return sprintf(buf, "%s\n", p->usb_pd ? "yes" : "no");
+}
+static DEVICE_ATTR_RO(supports_usb_power_delivery);
+
+static struct attribute *typec_partner_attrs[] = {
+	&dev_attr_accessory_mode.attr,
+	&dev_attr_supports_usb_power_delivery.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(typec_partner);
+
+static void typec_partner_release(struct device *dev)
+{
+	struct typec_partner *partner = to_typec_partner(dev);
+
+	kfree(partner);
+}
+
+static const struct device_type typec_partner_dev_type = {
+	.name = "typec_partner",
+	.groups = typec_partner_groups,
+	.release = typec_partner_release,
+};
+
+/**
+ * typec_partner_set_identity - Report result from Discover Identity command
+ * @partner: The partner updated identity values
+ *
+ * This routine is used to report that the result of Discover Identity USB power
+ * delivery command has become available.
+ */
+int typec_partner_set_identity(struct typec_partner *partner)
+{
+	if (!partner->identity)
+		return -EINVAL;
+
+	typec_report_identity(&partner->dev);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(typec_partner_set_identity);
+
+/**
+ * typec_partner_register_altmode - Register USB Type-C Partner Alternate Mode
+ * @partner: USB Type-C Partner that supports the alternate mode
+ * @desc: Description of the alternate mode
+ *
+ * This routine is used to register each alternate mode individually that
+ * @partner has listed in response to Discover SVIDs command. The modes for a
+ * SVID listed in response to Discover Modes command need to be listed in an
+ * array in @desc.
+ *
+ * Returns handle to the alternate mode on success or NULL on failure.
+ */
+struct typec_altmode *
+typec_partner_register_altmode(struct typec_partner *partner,
+			       struct typec_altmode_desc *desc)
+{
+	return typec_register_altmode(&partner->dev, desc);
+}
+EXPORT_SYMBOL_GPL(typec_partner_register_altmode);
+
+/**
+ * typec_register_partner - Register a USB Type-C Partner
+ * @port: The USB Type-C Port the partner is connected to
+ * @desc: Description of the partner
+ *
+ * Registers a device for USB Type-C Partner described in @desc.
+ *
+ * Returns handle to the partner on success or NULL on failure.
+ */
+struct typec_partner *typec_register_partner(struct typec_port *port,
+					     struct typec_partner_desc *desc)
+{
+	struct typec_partner *partner;
+	int ret;
+
+	partner = kzalloc(sizeof(*partner), GFP_KERNEL);
+	if (!partner)
+		return NULL;
+
+	partner->usb_pd = desc->usb_pd;
+	partner->accessory = desc->accessory;
+
+	if (desc->identity) {
+		/*
+		 * Creating directory for the identity only if the driver is
+		 * able to provide data to it.
+		 */
+		partner->dev.groups = usb_pd_id_groups;
+		partner->identity = desc->identity;
+	}
+
+	partner->dev.class = typec_class;
+	partner->dev.parent = &port->dev;
+	partner->dev.type = &typec_partner_dev_type;
+	dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev));
+
+	ret = device_register(&partner->dev);
+	if (ret) {
+		dev_err(&port->dev, "failed to register partner (%d)\n", ret);
+		put_device(&partner->dev);
+		return NULL;
+	}
+
+	return partner;
+}
+EXPORT_SYMBOL_GPL(typec_register_partner);
+
+/**
+ * typec_unregister_partner - Unregister a USB Type-C Partner
+ * @partner: The partner to be unregistered
+ *
+ * Unregister device created with typec_register_partner().
+ */
+void typec_unregister_partner(struct typec_partner *partner)
+{
+	if (partner)
+		device_unregister(&partner->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_partner);
+
+/* ------------------------------------------------------------------------- */
+/* Type-C Cable Plugs */
+
+static void typec_plug_release(struct device *dev)
+{
+	struct typec_plug *plug = to_typec_plug(dev);
+
+	kfree(plug);
+}
+
+static const struct device_type typec_plug_dev_type = {
+	.name = "typec_plug",
+	.release = typec_plug_release,
+};
+
+/**
+ * typec_plug_register_altmode - Register USB Type-C Cable Plug Alternate Mode
+ * @plug: USB Type-C Cable Plug that supports the alternate mode
+ * @desc: Description of the alternate mode
+ *
+ * This routine is used to register each alternate mode individually that @plug
+ * has listed in response to Discover SVIDs command. The modes for a SVID that
+ * the plug lists in response to Discover Modes command need to be listed in an
+ * array in @desc.
+ *
+ * Returns handle to the alternate mode on success or NULL on failure.
+ */
+struct typec_altmode *
+typec_plug_register_altmode(struct typec_plug *plug,
+			    struct typec_altmode_desc *desc)
+{
+	return typec_register_altmode(&plug->dev, desc);
+}
+EXPORT_SYMBOL_GPL(typec_plug_register_altmode);
+
+/**
+ * typec_register_plug - Register a USB Type-C Cable Plug
+ * @cable: USB Type-C Cable with the plug
+ * @desc: Description of the cable plug
+ *
+ * Registers a device for USB Type-C Cable Plug described in @desc. A USB Type-C
+ * Cable Plug represents a plug with electronics in it that can response to USB
+ * Power Delivery SOP Prime or SOP Double Prime packages.
+ *
+ * Returns handle to the cable plug on success or NULL on failure.
+ */
+struct typec_plug *typec_register_plug(struct typec_cable *cable,
+				       struct typec_plug_desc *desc)
+{
+	struct typec_plug *plug;
+	char name[8];
+	int ret;
+
+	plug = kzalloc(sizeof(*plug), GFP_KERNEL);
+	if (!plug)
+		return NULL;
+
+	sprintf(name, "plug%d", desc->index);
+
+	plug->index = desc->index;
+	plug->dev.class = typec_class;
+	plug->dev.parent = &cable->dev;
+	plug->dev.type = &typec_plug_dev_type;
+	dev_set_name(&plug->dev, "%s-%s", dev_name(cable->dev.parent), name);
+
+	ret = device_register(&plug->dev);
+	if (ret) {
+		dev_err(&cable->dev, "failed to register plug (%d)\n", ret);
+		put_device(&plug->dev);
+		return NULL;
+	}
+
+	return plug;
+}
+EXPORT_SYMBOL_GPL(typec_register_plug);
+
+/**
+ * typec_unregister_plug - Unregister a USB Type-C Cable Plug
+ * @plug: The cable plug to be unregistered
+ *
+ * Unregister device created with typec_register_plug().
+ */
+void typec_unregister_plug(struct typec_plug *plug)
+{
+	if (plug)
+		device_unregister(&plug->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_plug);
+
+/* Type-C Cables */
+
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_cable *cable = to_typec_cable(dev);
+
+	return sprintf(buf, "%s\n", cable->active ? "active" : "passive");
+}
+static DEVICE_ATTR_RO(type);
+
+static const char * const typec_plug_types[] = {
+	[USB_PLUG_NONE]		= "unknown",
+	[USB_PLUG_TYPE_A]	= "type-a",
+	[USB_PLUG_TYPE_B]	= "type-b",
+	[USB_PLUG_TYPE_C]	= "type-c",
+	[USB_PLUG_CAPTIVE]	= "captive",
+};
+
+static ssize_t plug_type_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct typec_cable *cable = to_typec_cable(dev);
+
+	return sprintf(buf, "%s\n", typec_plug_types[cable->type]);
+}
+static DEVICE_ATTR_RO(plug_type);
+
+static struct attribute *typec_cable_attrs[] = {
+	&dev_attr_type.attr,
+	&dev_attr_plug_type.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(typec_cable);
+
+static void typec_cable_release(struct device *dev)
+{
+	struct typec_cable *cable = to_typec_cable(dev);
+
+	kfree(cable);
+}
+
+static const struct device_type typec_cable_dev_type = {
+	.name = "typec_cable",
+	.groups = typec_cable_groups,
+	.release = typec_cable_release,
+};
+
+/**
+ * typec_cable_set_identity - Report result from Discover Identity command
+ * @cable: The cable updated identity values
+ *
+ * This routine is used to report that the result of Discover Identity USB power
+ * delivery command has become available.
+ */
+int typec_cable_set_identity(struct typec_cable *cable)
+{
+	if (!cable->identity)
+		return -EINVAL;
+
+	typec_report_identity(&cable->dev);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(typec_cable_set_identity);
+
+/**
+ * typec_register_cable - Register a USB Type-C Cable
+ * @port: The USB Type-C Port the cable is connected to
+ * @desc: Description of the cable
+ *
+ * Registers a device for USB Type-C Cable described in @desc. The cable will be
+ * parent for the optional cable plug devises.
+ *
+ * Returns handle to the cable on success or NULL on failure.
+ */
+struct typec_cable *typec_register_cable(struct typec_port *port,
+					 struct typec_cable_desc *desc)
+{
+	struct typec_cable *cable;
+	int ret;
+
+	cable = kzalloc(sizeof(*cable), GFP_KERNEL);
+	if (!cable)
+		return NULL;
+
+	cable->type = desc->type;
+	cable->active = desc->active;
+
+	if (desc->identity) {
+		/*
+		 * Creating directory for the identity only if the driver is
+		 * able to provide data to it.
+		 */
+		cable->dev.groups = usb_pd_id_groups;
+		cable->identity = desc->identity;
+	}
+
+	cable->dev.class = typec_class;
+	cable->dev.parent = &port->dev;
+	cable->dev.type = &typec_cable_dev_type;
+	dev_set_name(&cable->dev, "%s-cable", dev_name(&port->dev));
+
+	ret = device_register(&cable->dev);
+	if (ret) {
+		dev_err(&port->dev, "failed to register cable (%d)\n", ret);
+		put_device(&cable->dev);
+		return NULL;
+	}
+
+	return cable;
+}
+EXPORT_SYMBOL_GPL(typec_register_cable);
+
+/**
+ * typec_unregister_cable - Unregister a USB Type-C Cable
+ * @cable: The cable to be unregistered
+ *
+ * Unregister device created with typec_register_cable().
+ */
+void typec_unregister_cable(struct typec_cable *cable)
+{
+	if (cable)
+		device_unregister(&cable->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_cable);
+
+/* ------------------------------------------------------------------------- */
+/* USB Type-C ports */
+
+static const char * const typec_roles[] = {
+	[TYPEC_SINK]	= "sink",
+	[TYPEC_SOURCE]	= "source",
+};
+
+static const char * const typec_data_roles[] = {
+	[TYPEC_DEVICE]	= "device",
+	[TYPEC_HOST]	= "host",
+};
+
+static ssize_t
+preferred_role_store(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int role;
+	int ret;
+
+	if (port->cap->type != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "Preferred role only supported with DRP ports\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->try_role) {
+		dev_dbg(dev, "Setting preferred role not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	role = sysfs_match_string(typec_roles, buf);
+	if (role < 0) {
+		if (sysfs_streq(buf, "none"))
+			role = TYPEC_NO_PREFERRED_ROLE;
+		else
+			return -EINVAL;
+	}
+
+	ret = port->cap->try_role(port->cap, role);
+	if (ret)
+		return ret;
+
+	port->prefer_role = role;
+	return size;
+}
+
+static ssize_t
+preferred_role_show(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->cap->type != TYPEC_PORT_DRP)
+		return 0;
+
+	if (port->prefer_role < 0)
+		return 0;
+
+	return sprintf(buf, "%s\n", typec_roles[port->prefer_role]);
+}
+static DEVICE_ATTR_RW(preferred_role);
+
+static ssize_t data_role_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int ret;
+
+	if (port->cap->type != TYPEC_PORT_DRP) {
+		dev_dbg(dev, "data role swap only supported with DRP ports\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->dr_set) {
+		dev_dbg(dev, "data role swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	ret = sysfs_match_string(typec_data_roles, buf);
+	if (ret < 0)
+		return ret;
+
+	ret = port->cap->dr_set(port->cap, ret);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t data_role_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->cap->type == TYPEC_PORT_DRP)
+		return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ?
+			       "[host] device" : "host [device]");
+
+	return sprintf(buf, "[%s]\n", typec_data_roles[port->data_role]);
+}
+static DEVICE_ATTR_RW(data_role);
+
+static ssize_t power_role_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	int ret = size;
+
+	if (!port->cap->pd_revision) {
+		dev_dbg(dev, "USB Power Delivery not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->pr_set) {
+		dev_dbg(dev, "power role swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
+		dev_dbg(dev, "partner unable to swap power role\n");
+		return -EIO;
+	}
+
+	ret = sysfs_match_string(typec_roles, buf);
+	if (ret < 0)
+		return ret;
+
+	ret = port->cap->pr_set(port->cap, ret);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t power_role_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	if (port->cap->type == TYPEC_PORT_DRP)
+		return sprintf(buf, "%s\n", port->pwr_role == TYPEC_SOURCE ?
+			       "[source] sink" : "source [sink]");
+
+	return sprintf(buf, "[%s]\n", typec_roles[port->pwr_role]);
+}
+static DEVICE_ATTR_RW(power_role);
+
+static const char * const typec_pwr_opmodes[] = {
+	[TYPEC_PWR_MODE_USB]	= "default",
+	[TYPEC_PWR_MODE_1_5A]	= "1.5A",
+	[TYPEC_PWR_MODE_3_0A]	= "3.0A",
+	[TYPEC_PWR_MODE_PD]	= "usb_power_delivery",
+};
+
+static ssize_t power_operation_mode_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]);
+}
+static DEVICE_ATTR_RO(power_operation_mode);
+
+static ssize_t vconn_source_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	struct typec_port *port = to_typec_port(dev);
+	bool source;
+	int ret;
+
+	if (!port->cap->pd_revision) {
+		dev_dbg(dev, "VCONN swap depends on USB Power Delivery\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!port->cap->vconn_set) {
+		dev_dbg(dev, "VCONN swapping not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	ret = kstrtobool(buf, &source);
+	if (ret)
+		return ret;
+
+	ret = port->cap->vconn_set(port->cap, (enum typec_role)source);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t vconn_source_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	return sprintf(buf, "%s\n",
+		       port->vconn_role == TYPEC_SOURCE ? "yes" : "no");
+}
+static DEVICE_ATTR_RW(vconn_source);
+
+static ssize_t supported_accessory_modes_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	ssize_t ret = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(port->cap->accessory); i++) {
+		if (port->cap->accessory[i])
+			ret += sprintf(buf + ret, "%s ",
+			       typec_accessory_modes[port->cap->accessory[i]]);
+	}
+
+	if (!ret)
+		return sprintf(buf, "none\n");
+
+	buf[ret - 1] = '\n';
+
+	return ret;
+}
+static DEVICE_ATTR_RO(supported_accessory_modes);
+
+static ssize_t usb_typec_revision_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct typec_port *port = to_typec_port(dev);
+	u16 rev = port->cap->revision;
+
+	return sprintf(buf, "%d.%d\n", (rev >> 8) & 0xff, (rev >> 4) & 0xf);
+}
+static DEVICE_ATTR_RO(usb_typec_revision);
+
+static ssize_t usb_power_delivery_revision_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct typec_port *p = to_typec_port(dev);
+
+	return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff);
+}
+static DEVICE_ATTR_RO(usb_power_delivery_revision);
+
+static struct attribute *typec_attrs[] = {
+	&dev_attr_data_role.attr,
+	&dev_attr_power_operation_mode.attr,
+	&dev_attr_power_role.attr,
+	&dev_attr_preferred_role.attr,
+	&dev_attr_supported_accessory_modes.attr,
+	&dev_attr_usb_power_delivery_revision.attr,
+	&dev_attr_usb_typec_revision.attr,
+	&dev_attr_vconn_source.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(typec);
+
+static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	int ret;
+
+	ret = add_uevent_var(env, "TYPEC_PORT=%s", dev_name(dev));
+	if (ret)
+		dev_err(dev, "failed to add uevent TYPEC_PORT\n");
+
+	return ret;
+}
+
+static void typec_release(struct device *dev)
+{
+	struct typec_port *port = to_typec_port(dev);
+
+	ida_simple_remove(&typec_index_ida, port->id);
+	kfree(port);
+}
+
+static const struct device_type typec_port_dev_type = {
+	.name = "typec_port",
+	.groups = typec_groups,
+	.uevent = typec_uevent,
+	.release = typec_release,
+};
+
+/* --------------------------------------- */
+/* Driver callbacks to report role updates */
+
+/**
+ * typec_set_data_role - Report data role change
+ * @port: The USB Type-C Port where the role was changed
+ * @role: The new data role
+ *
+ * This routine is used by the port drivers to report data role changes.
+ */
+void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
+{
+	if (port->data_role == role)
+		return;
+
+	port->data_role = role;
+	sysfs_notify(&port->dev.kobj, NULL, "data_role");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_set_data_role);
+
+/**
+ * typec_set_pwr_role - Report power role change
+ * @port: The USB Type-C Port where the role was changed
+ * @role: The new data role
+ *
+ * This routine is used by the port drivers to report power role changes.
+ */
+void typec_set_pwr_role(struct typec_port *port, enum typec_role role)
+{
+	if (port->pwr_role == role)
+		return;
+
+	port->pwr_role = role;
+	sysfs_notify(&port->dev.kobj, NULL, "power_role");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_set_pwr_role);
+
+/**
+ * typec_set_pwr_role - Report VCONN source change
+ * @port: The USB Type-C Port which VCONN role changed
+ * @role: Source when @port is sourcing VCONN, or Sink when it's not
+ *
+ * This routine is used by the port drivers to report if the VCONN source is
+ * changes.
+ */
+void typec_set_vconn_role(struct typec_port *port, enum typec_role role)
+{
+	if (port->vconn_role == role)
+		return;
+
+	port->vconn_role = role;
+	sysfs_notify(&port->dev.kobj, NULL, "vconn_source");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_set_vconn_role);
+
+/**
+ * typec_set_pwr_opmode - Report changed power operation mode
+ * @port: The USB Type-C Port where the mode was changed
+ * @opmode: New power operation mode
+ *
+ * This routine is used by the port drivers to report changed power operation
+ * mode in @port. The modes are USB (default), 1.5A, 3.0A as defined in USB
+ * Type-C specification, and "USB Power Delivery" when the power levels are
+ * negotiated with methods defined in USB Power Delivery specification.
+ */
+void typec_set_pwr_opmode(struct typec_port *port,
+			  enum typec_pwr_opmode opmode)
+{
+	if (port->pwr_opmode == opmode)
+		return;
+
+	port->pwr_opmode = opmode;
+	sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode");
+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
+}
+EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);
+
+/* --------------------------------------- */
+
+/**
+ * typec_port_register_altmode - Register USB Type-C Port Alternate Mode
+ * @port: USB Type-C Port that supports the alternate mode
+ * @desc: Description of the alternate mode
+ *
+ * This routine is used to register an alternate mode that @port is capable of
+ * supporting.
+ *
+ * Returns handle to the alternate mode on success or NULL on failure.
+ */
+struct typec_altmode *
+typec_port_register_altmode(struct typec_port *port,
+			    struct typec_altmode_desc *desc)
+{
+	return typec_register_altmode(&port->dev, desc);
+}
+EXPORT_SYMBOL_GPL(typec_port_register_altmode);
+
+/**
+ * typec_register_port - Register a USB Type-C Port
+ * @parent: Parent device
+ * @cap: Description of the port
+ *
+ * Registers a device for USB Type-C Port described in @cap.
+ *
+ * Returns handle to the port on success or NULL on failure.
+ */
+struct typec_port *typec_register_port(struct device *parent,
+				       const struct typec_capability *cap)
+{
+	struct typec_port *port;
+	int role;
+	int ret;
+	int id;
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	if (!port)
+		return NULL;
+
+	id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		kfree(port);
+		return NULL;
+	}
+
+	if (cap->type == TYPEC_PORT_DFP)
+		role = TYPEC_SOURCE;
+	else if (cap->type == TYPEC_PORT_UFP)
+		role = TYPEC_SINK;
+	else
+		role = cap->prefer_role;
+
+	if (role == TYPEC_SOURCE) {
+		port->data_role = TYPEC_HOST;
+		port->pwr_role = TYPEC_SOURCE;
+		port->vconn_role = TYPEC_SOURCE;
+	} else {
+		port->data_role = TYPEC_DEVICE;
+		port->pwr_role = TYPEC_SINK;
+		port->vconn_role = TYPEC_SINK;
+	}
+
+	port->id = id;
+	port->cap = cap;
+	port->prefer_role = cap->prefer_role;
+
+	port->dev.class = typec_class;
+	port->dev.parent = parent;
+	port->dev.fwnode = cap->fwnode;
+	port->dev.type = &typec_port_dev_type;
+	dev_set_name(&port->dev, "port%d", id);
+
+	ret = device_register(&port->dev);
+	if (ret) {
+		dev_err(parent, "failed to register port (%d)\n", ret);
+		put_device(&port->dev);
+		return NULL;
+	}
+
+	return port;
+}
+EXPORT_SYMBOL_GPL(typec_register_port);
+
+/**
+ * typec_unregister_port - Unregister a USB Type-C Port
+ * @port: The port to be unregistered
+ *
+ * Unregister device created with typec_register_port().
+ */
+void typec_unregister_port(struct typec_port *port)
+{
+	if (port)
+		device_unregister(&port->dev);
+}
+EXPORT_SYMBOL_GPL(typec_unregister_port);
+
+static int __init typec_init(void)
+{
+	typec_class = class_create(THIS_MODULE, "typec");
+	return PTR_ERR_OR_ZERO(typec_class);
+}
+subsys_initcall(typec_init);
+
+static void __exit typec_exit(void)
+{
+	class_destroy(typec_class);
+	ida_destroy(&typec_index_ida);
+}
+module_exit(typec_exit);
+
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("USB Type-C Connector Class");
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
new file mode 100644
index 000000000000..ec78204964ab
--- /dev/null
+++ b/include/linux/usb/typec.h
@@ -0,0 +1,243 @@
+
+#ifndef __LINUX_USB_TYPEC_H
+#define __LINUX_USB_TYPEC_H
+
+#include <linux/types.h>
+
+/* XXX: Once we have a header for USB Power Delivery, this belongs there */
+#define ALTMODE_MAX_MODES	6
+
+/* USB Type-C Specification releases */
+#define USB_TYPEC_REV_1_0	0x100 /* 1.0 */
+#define USB_TYPEC_REV_1_1	0x110 /* 1.1 */
+#define USB_TYPEC_REV_1_2	0x120 /* 1.2 */
+
+struct typec_altmode;
+struct typec_partner;
+struct typec_cable;
+struct typec_plug;
+struct typec_port;
+
+struct fwnode_handle;
+
+enum typec_port_type {
+	TYPEC_PORT_DFP,
+	TYPEC_PORT_UFP,
+	TYPEC_PORT_DRP,
+};
+
+enum typec_plug_type {
+	USB_PLUG_NONE,
+	USB_PLUG_TYPE_A,
+	USB_PLUG_TYPE_B,
+	USB_PLUG_TYPE_C,
+	USB_PLUG_CAPTIVE,
+};
+
+enum typec_data_role {
+	TYPEC_DEVICE,
+	TYPEC_HOST,
+};
+
+enum typec_role {
+	TYPEC_SINK,
+	TYPEC_SOURCE,
+};
+
+enum typec_pwr_opmode {
+	TYPEC_PWR_MODE_USB,
+	TYPEC_PWR_MODE_1_5A,
+	TYPEC_PWR_MODE_3_0A,
+	TYPEC_PWR_MODE_PD,
+};
+
+enum typec_accessory {
+	TYPEC_ACCESSORY_NONE,
+	TYPEC_ACCESSORY_AUDIO,
+	TYPEC_ACCESSORY_DEBUG,
+};
+
+#define TYPEC_MAX_ACCESSORY	3
+
+/*
+ * struct usb_pd_identity - USB Power Delivery identity data
+ * @id_header: ID Header VDO
+ * @cert_stat: Cert Stat VDO
+ * @product: Product VDO
+ *
+ * USB power delivery Discover Identity command response data.
+ *
+ * REVISIT: This is USB Power Delivery specific information, so this structure
+ * probable belongs to USB Power Delivery header file once we have them.
+ */
+struct usb_pd_identity {
+	u32			id_header;
+	u32			cert_stat;
+	u32			product;
+};
+
+int typec_partner_set_identity(struct typec_partner *partner);
+int typec_cable_set_identity(struct typec_cable *cable);
+
+/*
+ * struct typec_mode_desc - Individual Mode of an Alternate Mode
+ * @index: Index of the Mode within the SVID
+ * @vdo: VDO returned by Discover Modes USB PD command
+ * @desc: Optional human readable description of the mode
+ * @roles: Only for ports. DRP if the mode is available in both roles
+ *
+ * Description of a mode of an Alternate Mode which a connector, cable plug or
+ * partner supports. Every mode will have it's own sysfs group. The details are
+ * the VDO returned by discover modes command, description for the mode and
+ * active flag telling has the mode being entered or not.
+ */
+struct typec_mode_desc {
+	int			index;
+	u32			vdo;
+	char			*desc;
+	/* Only used with ports */
+	enum typec_port_type	roles;
+};
+
+/*
+ * struct typec_altmode_desc - USB Type-C Alternate Mode Descriptor
+ * @svid: Standard or Vendor ID
+ * @n_modes: Number of modes
+ * @modes: Array of modes supported by the Alternate Mode
+ *
+ * Representation of an Alternate Mode that has SVID assigned by USB-IF. The
+ * array of modes will list the modes of a particular SVID that are supported by
+ * a connector, partner of a cable plug.
+ */
+struct typec_altmode_desc {
+	u16			svid;
+	int			n_modes;
+	struct typec_mode_desc	modes[ALTMODE_MAX_MODES];
+};
+
+struct typec_altmode
+*typec_partner_register_altmode(struct typec_partner *partner,
+				struct typec_altmode_desc *desc);
+struct typec_altmode
+*typec_plug_register_altmode(struct typec_plug *plug,
+			     struct typec_altmode_desc *desc);
+struct typec_altmode
+*typec_port_register_altmode(struct typec_port *port,
+			     struct typec_altmode_desc *desc);
+void typec_unregister_altmode(struct typec_altmode *altmode);
+
+struct typec_port *typec_altmode2port(struct typec_altmode *alt);
+
+void typec_altmode_update_active(struct typec_altmode *alt, int mode,
+				 bool active);
+
+enum typec_plug_index {
+	TYPEC_PLUG_SOP_P,
+	TYPEC_PLUG_SOP_PP,
+};
+
+/*
+ * struct typec_plug_desc - USB Type-C Cable Plug Descriptor
+ * @index: SOP Prime for the plug connected to DFP and SOP Double Prime for the
+ *         plug connected to UFP
+ *
+ * Represents USB Type-C Cable Plug.
+ */
+struct typec_plug_desc {
+	enum typec_plug_index	index;
+};
+
+/*
+ * struct typec_cable_desc - USB Type-C Cable Descriptor
+ * @type: The plug type from USB PD Cable VDO
+ * @active: Is the cable active or passive
+ * @identity: Result of Discover Identity command
+ *
+ * Represents USB Type-C Cable attached to USB Type-C port.
+ */
+struct typec_cable_desc {
+	enum typec_plug_type	type;
+	unsigned int		active:1;
+	struct usb_pd_identity	*identity;
+};
+
+/*
+ * struct typec_partner_desc - USB Type-C Partner Descriptor
+ * @usb_pd: USB Power Delivery support
+ * @accessory: Audio, Debug or none.
+ * @identity: Discover Identity command data
+ *
+ * Details about a partner that is attached to USB Type-C port. If @identity
+ * member exists when partner is registered, a directory named "identity" is
+ * created to sysfs for the partner device.
+ */
+struct typec_partner_desc {
+	unsigned int		usb_pd:1;
+	enum typec_accessory	accessory;
+	struct usb_pd_identity	*identity;
+};
+
+/*
+ * struct typec_capability - USB Type-C Port Capabilities
+ * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role)
+ * @revision: USB Type-C Specification release. Binary coded decimal
+ * @pd_revision: USB Power Delivery Specification revision if supported
+ * @prefer_role: Initial role preference
+ * @accessory: Supported Accessory Modes
+ * @fwnode: Optional fwnode of the port
+ * @try_role: Set data role preference for DRP port
+ * @dr_set: Set Data Role
+ * @pr_set: Set Power Role
+ * @vconn_set: Set VCONN Role
+ * @activate_mode: Enter/exit given Alternate Mode
+ *
+ * Static capabilities of a single USB Type-C port.
+ */
+struct typec_capability {
+	enum typec_port_type	type;
+	u16			revision; /* 0120H = "1.2" */
+	u16			pd_revision; /* 0300H = "3.0" */
+	int			prefer_role;
+	enum typec_accessory	accessory[TYPEC_MAX_ACCESSORY];
+
+	struct fwnode_handle	*fwnode;
+
+	int		(*try_role)(const struct typec_capability *,
+				    int role);
+
+	int		(*dr_set)(const struct typec_capability *,
+				  enum typec_data_role);
+	int		(*pr_set)(const struct typec_capability *,
+				  enum typec_role);
+	int		(*vconn_set)(const struct typec_capability *,
+				     enum typec_role);
+
+	int		(*activate_mode)(const struct typec_capability *,
+					 int mode, int activate);
+};
+
+/* Specific to try_role(). Indicates the user want's to clear the preference. */
+#define TYPEC_NO_PREFERRED_ROLE	(-1)
+
+struct typec_port *typec_register_port(struct device *parent,
+				       const struct typec_capability *cap);
+void typec_unregister_port(struct typec_port *port);
+
+struct typec_partner *typec_register_partner(struct typec_port *port,
+					     struct typec_partner_desc *desc);
+void typec_unregister_partner(struct typec_partner *partner);
+
+struct typec_cable *typec_register_cable(struct typec_port *port,
+					 struct typec_cable_desc *desc);
+void typec_unregister_cable(struct typec_cable *cable);
+
+struct typec_plug *typec_register_plug(struct typec_cable *cable,
+				       struct typec_plug_desc *desc);
+void typec_unregister_plug(struct typec_plug *plug);
+
+void typec_set_data_role(struct typec_port *port, enum typec_data_role role);
+void typec_set_pwr_role(struct typec_port *port, enum typec_role role);
+void typec_set_vconn_role(struct typec_port *port, enum typec_role role);
+void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode);
+
+#endif /* __LINUX_USB_TYPEC_H */
-- 
2.11.0

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

* [PATCH v17 3/3] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY
  2017-02-21 14:24 [PATCH v17 0/3] USB Type-C Connector class Heikki Krogerus
  2017-02-21 14:24 ` [PATCH v17 1/3] lib/string: add sysfs_match_string helper Heikki Krogerus
  2017-02-21 14:24 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
@ 2017-02-21 14:24 ` Heikki Krogerus
  2017-02-21 15:42 ` [PATCH v17 0/3] USB Type-C Connector class Felipe Balbi
  2017-03-21 10:23 ` Greg KH
  4 siblings, 0 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-02-21 14:24 UTC (permalink / raw)
  To: Greg KH
  Cc: Guenter Roeck, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

This adds driver for the USB Type-C PHY on Intel WhiskeyCove
PMIC which is available on some of the Intel Broxton SoC
based platforms.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Tested-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/usb/typec/Kconfig       |  15 ++
 drivers/usb/typec/Makefile      |   1 +
 drivers/usb/typec/typec_wcove.c | 377 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 393 insertions(+)
 create mode 100644 drivers/usb/typec/typec_wcove.c

diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 17792f9114c6..dfcfe459b7cf 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -4,4 +4,19 @@ menu "USB Power Delivery and Type-C drivers"
 config TYPEC
 	tristate
 
+config TYPEC_WCOVE
+	tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"
+	depends on ACPI
+	depends on INTEL_SOC_PMIC
+	depends on INTEL_PMC_IPC
+	depends on BXT_WC_PMIC_OPREGION
+	select TYPEC
+	help
+	  This driver adds support for USB Type-C detection on Intel Broxton
+	  platforms that have Intel Whiskey Cove PMIC. The driver can detect the
+	  role and cable orientation.
+
+	  To compile this driver as module, choose M here: the module will be
+	  called typec_wcove
+
 endmenu
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index 1012a8bed6d5..b9cb862221af 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_TYPEC)		+= typec.o
+obj-$(CONFIG_TYPEC_WCOVE)	+= typec_wcove.o
diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/typec_wcove.c
new file mode 100644
index 000000000000..d5a7b21fa3f1
--- /dev/null
+++ b/drivers/usb/typec/typec_wcove.c
@@ -0,0 +1,377 @@
+/**
+ * typec_wcove.c - WhiskeyCove PMIC USB Type-C PHY driver
+ *
+ * Copyright (C) 2017 Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.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 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/usb/typec.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/intel_soc_pmic.h>
+
+/* Register offsets */
+#define WCOVE_CHGRIRQ0		0x4e09
+#define WCOVE_PHYCTRL		0x5e07
+
+#define USBC_CONTROL1		0x7001
+#define USBC_CONTROL2		0x7002
+#define USBC_CONTROL3		0x7003
+#define USBC_CC1_CTRL		0x7004
+#define USBC_CC2_CTRL		0x7005
+#define USBC_STATUS1		0x7007
+#define USBC_STATUS2		0x7008
+#define USBC_STATUS3		0x7009
+#define USBC_IRQ1		0x7015
+#define USBC_IRQ2		0x7016
+#define USBC_IRQMASK1		0x7017
+#define USBC_IRQMASK2		0x7018
+
+/* Register bits */
+
+#define USBC_CONTROL1_MODE_DRP(r)	(((r) & ~0x7) | 4)
+
+#define USBC_CONTROL2_UNATT_SNK		BIT(0)
+#define USBC_CONTROL2_UNATT_SRC		BIT(1)
+#define USBC_CONTROL2_DIS_ST		BIT(2)
+
+#define USBC_CONTROL3_PD_DIS		BIT(1)
+
+#define USBC_CC_CTRL_VCONN_EN		BIT(1)
+
+#define USBC_STATUS1_DET_ONGOING	BIT(6)
+#define USBC_STATUS1_RSLT(r)		((r) & 0xf)
+#define USBC_RSLT_NOTHING		0
+#define USBC_RSLT_SRC_DEFAULT		1
+#define USBC_RSLT_SRC_1_5A		2
+#define USBC_RSLT_SRC_3_0A		3
+#define USBC_RSLT_SNK			4
+#define USBC_RSLT_DEBUG_ACC		5
+#define USBC_RSLT_AUDIO_ACC		6
+#define USBC_RSLT_UNDEF			15
+#define USBC_STATUS1_ORIENT(r)		(((r) >> 4) & 0x3)
+#define USBC_ORIENT_NORMAL		1
+#define USBC_ORIENT_REVERSE		2
+
+#define USBC_STATUS2_VBUS_REQ		BIT(5)
+
+#define USBC_IRQ1_ADCDONE1		BIT(2)
+#define USBC_IRQ1_OVERTEMP		BIT(1)
+#define USBC_IRQ1_SHORT			BIT(0)
+
+#define USBC_IRQ2_CC_CHANGE		BIT(7)
+#define USBC_IRQ2_RX_PD			BIT(6)
+#define USBC_IRQ2_RX_HR			BIT(5)
+#define USBC_IRQ2_RX_CR			BIT(4)
+#define USBC_IRQ2_TX_SUCCESS		BIT(3)
+#define USBC_IRQ2_TX_FAIL		BIT(2)
+
+#define USBC_IRQMASK1_ALL	(USBC_IRQ1_ADCDONE1 | USBC_IRQ1_OVERTEMP | \
+				 USBC_IRQ1_SHORT)
+
+#define USBC_IRQMASK2_ALL	(USBC_IRQ2_CC_CHANGE | USBC_IRQ2_RX_PD | \
+				 USBC_IRQ2_RX_HR | USBC_IRQ2_RX_CR | \
+				 USBC_IRQ2_TX_SUCCESS | USBC_IRQ2_TX_FAIL)
+
+struct wcove_typec {
+	struct mutex lock; /* device lock */
+	struct device *dev;
+	struct regmap *regmap;
+	struct typec_port *port;
+	struct typec_capability cap;
+	struct typec_partner *partner;
+};
+
+enum wcove_typec_func {
+	WCOVE_FUNC_DRIVE_VBUS = 1,
+	WCOVE_FUNC_ORIENTATION,
+	WCOVE_FUNC_ROLE,
+	WCOVE_FUNC_DRIVE_VCONN,
+};
+
+enum wcove_typec_orientation {
+	WCOVE_ORIENTATION_NORMAL,
+	WCOVE_ORIENTATION_REVERSE,
+};
+
+enum wcove_typec_role {
+	WCOVE_ROLE_HOST,
+	WCOVE_ROLE_DEVICE,
+};
+
+static uuid_le uuid = UUID_LE(0x482383f0, 0x2876, 0x4e49,
+			      0x86, 0x85, 0xdb, 0x66, 0x21, 0x1a, 0xf0, 0x37);
+
+static int wcove_typec_func(struct wcove_typec *wcove,
+			    enum wcove_typec_func func, int param)
+{
+	union acpi_object *obj;
+	union acpi_object tmp;
+	union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
+
+	tmp.type = ACPI_TYPE_INTEGER;
+	tmp.integer.value = param;
+
+	obj = acpi_evaluate_dsm(ACPI_HANDLE(wcove->dev), uuid.b, 1, func,
+				&argv4);
+	if (!obj) {
+		dev_err(wcove->dev, "%s: failed to evaluate _DSM\n", __func__);
+		return -EIO;
+	}
+
+	ACPI_FREE(obj);
+	return 0;
+}
+
+static irqreturn_t wcove_typec_irq(int irq, void *data)
+{
+	enum typec_role role = TYPEC_SINK;
+	struct typec_partner_desc partner;
+	struct wcove_typec *wcove = data;
+	unsigned int cc1_ctrl;
+	unsigned int cc2_ctrl;
+	unsigned int cc_irq1;
+	unsigned int cc_irq2;
+	unsigned int status1;
+	unsigned int status2;
+	int ret;
+
+	mutex_lock(&wcove->lock);
+
+	ret = regmap_read(wcove->regmap, USBC_IRQ1, &cc_irq1);
+	if (ret)
+		goto err;
+
+	ret = regmap_read(wcove->regmap, USBC_IRQ2, &cc_irq2);
+	if (ret)
+		goto err;
+
+	ret = regmap_read(wcove->regmap, USBC_STATUS1, &status1);
+	if (ret)
+		goto err;
+
+	ret = regmap_read(wcove->regmap, USBC_STATUS2, &status2);
+	if (ret)
+		goto err;
+
+	ret = regmap_read(wcove->regmap, USBC_CC1_CTRL, &cc1_ctrl);
+	if (ret)
+		goto err;
+
+	ret = regmap_read(wcove->regmap, USBC_CC2_CTRL, &cc2_ctrl);
+	if (ret)
+		goto err;
+
+	if (cc_irq1) {
+		if (cc_irq1 & USBC_IRQ1_OVERTEMP)
+			dev_err(wcove->dev, "VCONN Switch Over Temperature!\n");
+		if (cc_irq1 & USBC_IRQ1_SHORT)
+			dev_err(wcove->dev, "VCONN Switch Short Circuit!\n");
+		ret = regmap_write(wcove->regmap, USBC_IRQ1, cc_irq1);
+		if (ret)
+			goto err;
+	}
+
+	if (cc_irq2) {
+		ret = regmap_write(wcove->regmap, USBC_IRQ2, cc_irq2);
+		if (ret)
+			goto err;
+		/*
+		 * Ignoring any PD communication interrupts until the PD support
+		 * is available
+		 */
+		if (cc_irq2 & ~USBC_IRQ2_CC_CHANGE) {
+			dev_WARN(wcove->dev, "USB PD handling missing\n");
+			goto err;
+		}
+	}
+
+	if (status1 & USBC_STATUS1_DET_ONGOING)
+		goto out;
+
+	if (USBC_STATUS1_RSLT(status1) == USBC_RSLT_NOTHING) {
+		if (wcove->partner) {
+			typec_unregister_partner(wcove->partner);
+			wcove->partner = NULL;
+		}
+
+		wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION,
+				 WCOVE_ORIENTATION_NORMAL);
+
+		/* This makes sure the device controller is disconnected */
+		wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_HOST);
+
+		/* Port to default role */
+		typec_set_data_role(wcove->port, TYPEC_DEVICE);
+		typec_set_pwr_role(wcove->port, TYPEC_SINK);
+		typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_USB);
+
+		goto out;
+	}
+
+	if (wcove->partner)
+		goto out;
+
+	switch (USBC_STATUS1_ORIENT(status1)) {
+	case USBC_ORIENT_NORMAL:
+		wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION,
+				 WCOVE_ORIENTATION_NORMAL);
+		break;
+	case USBC_ORIENT_REVERSE:
+		wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION,
+				 WCOVE_ORIENTATION_REVERSE);
+	default:
+		break;
+	}
+
+	memset(&partner, 0, sizeof(partner));
+
+	switch (USBC_STATUS1_RSLT(status1)) {
+	case USBC_RSLT_SRC_DEFAULT:
+		typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_USB);
+		break;
+	case USBC_RSLT_SRC_1_5A:
+		typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_1_5A);
+		break;
+	case USBC_RSLT_SRC_3_0A:
+		typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_3_0A);
+		break;
+	case USBC_RSLT_SNK:
+		role = TYPEC_SOURCE;
+		break;
+	case USBC_RSLT_DEBUG_ACC:
+		partner.accessory = TYPEC_ACCESSORY_DEBUG;
+		break;
+	case USBC_RSLT_AUDIO_ACC:
+		partner.accessory = TYPEC_ACCESSORY_AUDIO;
+		break;
+	default:
+		dev_WARN(wcove->dev, "%s Undefined result\n", __func__);
+		goto err;
+	}
+
+	if (role == TYPEC_SINK) {
+		wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_DEVICE);
+		typec_set_data_role(wcove->port, TYPEC_DEVICE);
+		typec_set_pwr_role(wcove->port, TYPEC_SINK);
+	} else {
+		wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_HOST);
+		typec_set_pwr_role(wcove->port, TYPEC_SOURCE);
+		typec_set_data_role(wcove->port, TYPEC_HOST);
+	}
+
+	wcove->partner = typec_register_partner(wcove->port, &partner);
+	if (!wcove->partner)
+		dev_err(wcove->dev, "failed register partner\n");
+out:
+	/* If either CC pins is requesting VCONN, we turn it on */
+	if ((cc1_ctrl & USBC_CC_CTRL_VCONN_EN) ||
+	    (cc2_ctrl &	USBC_CC_CTRL_VCONN_EN))
+		wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VCONN, true);
+	else
+		wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VCONN, false);
+
+	/* Relying on the FSM to know when we need to drive VBUS. */
+	wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VBUS,
+			 !!(status2 & USBC_STATUS2_VBUS_REQ));
+err:
+	/* REVISIT: Clear WhiskeyCove CHGR Type-C interrupt */
+	regmap_write(wcove->regmap, WCOVE_CHGRIRQ0, BIT(5));
+
+	mutex_unlock(&wcove->lock);
+	return IRQ_HANDLED;
+}
+
+static int wcove_typec_probe(struct platform_device *pdev)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+	struct wcove_typec *wcove;
+	unsigned int val;
+	int ret;
+
+	wcove = devm_kzalloc(&pdev->dev, sizeof(*wcove), GFP_KERNEL);
+	if (!wcove)
+		return -ENOMEM;
+
+	mutex_init(&wcove->lock);
+	wcove->dev = &pdev->dev;
+	wcove->regmap = pmic->regmap;
+
+	ret = regmap_irq_get_virq(pmic->irq_chip_data_level2,
+				  platform_get_irq(pdev, 0));
+	if (ret < 0)
+		return ret;
+
+	ret = devm_request_threaded_irq(&pdev->dev, ret, NULL,
+					wcove_typec_irq, IRQF_ONESHOT,
+					"wcove_typec", wcove);
+	if (ret)
+		return ret;
+
+	if (!acpi_check_dsm(ACPI_HANDLE(&pdev->dev), uuid.b, 0, 0x1f)) {
+		dev_err(&pdev->dev, "Missing _DSM functions\n");
+		return -ENODEV;
+	}
+
+	wcove->cap.type = TYPEC_PORT_DRP;
+	wcove->cap.revision = USB_TYPEC_REV_1_1;
+	wcove->cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
+
+	/* Make sure the PD PHY is disabled until USB PD is available */
+	regmap_read(wcove->regmap, USBC_CONTROL3, &val);
+	regmap_write(wcove->regmap, USBC_CONTROL3, val | USBC_CONTROL3_PD_DIS);
+
+	/* DRP mode without accessory support */
+	regmap_read(wcove->regmap, USBC_CONTROL1, &val);
+	regmap_write(wcove->regmap, USBC_CONTROL1, USBC_CONTROL1_MODE_DRP(val));
+
+	wcove->port = typec_register_port(&pdev->dev, &wcove->cap);
+	if (!wcove->port)
+		return -ENODEV;
+
+	/* Unmask everything */
+	regmap_read(wcove->regmap, USBC_IRQMASK1, &val);
+	regmap_write(wcove->regmap, USBC_IRQMASK1, val & ~USBC_IRQMASK1_ALL);
+	regmap_read(wcove->regmap, USBC_IRQMASK2, &val);
+	regmap_write(wcove->regmap, USBC_IRQMASK2, val & ~USBC_IRQMASK2_ALL);
+
+	platform_set_drvdata(pdev, wcove);
+	return 0;
+}
+
+static int wcove_typec_remove(struct platform_device *pdev)
+{
+	struct wcove_typec *wcove = platform_get_drvdata(pdev);
+	unsigned int val;
+
+	/* Mask everything */
+	regmap_read(wcove->regmap, USBC_IRQMASK1, &val);
+	regmap_write(wcove->regmap, USBC_IRQMASK1, val | USBC_IRQMASK1_ALL);
+	regmap_read(wcove->regmap, USBC_IRQMASK2, &val);
+	regmap_write(wcove->regmap, USBC_IRQMASK2, val | USBC_IRQMASK2_ALL);
+
+	typec_unregister_partner(wcove->partner);
+	typec_unregister_port(wcove->port);
+	return 0;
+}
+
+static struct platform_driver wcove_typec_driver = {
+	.driver = {
+		.name		= "bxt_wcove_usbc",
+	},
+	.probe			= wcove_typec_probe,
+	.remove			= wcove_typec_remove,
+};
+
+module_platform_driver(wcove_typec_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("WhiskeyCove PMIC USB Type-C PHY driver");
+MODULE_ALIAS("platform:bxt_wcove_usbc");
-- 
2.11.0

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

* Re: [PATCH v17 0/3] USB Type-C Connector class
  2017-02-21 14:24 [PATCH v17 0/3] USB Type-C Connector class Heikki Krogerus
                   ` (2 preceding siblings ...)
  2017-02-21 14:24 ` [PATCH v17 3/3] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY Heikki Krogerus
@ 2017-02-21 15:42 ` Felipe Balbi
  2017-03-21 11:14   ` Heikki Krogerus
  2017-03-21 10:23 ` Greg KH
  4 siblings, 1 reply; 64+ messages in thread
From: Felipe Balbi @ 2017-02-21 15:42 UTC (permalink / raw)
  To: Heikki Krogerus, Greg KH
  Cc: Guenter Roeck, Oliver Neukum, linux-kernel, linux-usb


Hi,

Heikki Krogerus <heikki.krogerus@linux.intel.com> writes:
> The USB Type-C class is meant to provide unified interface to the
> userspace to present the USB Type-C ports in a system.
>
> Changes since v16:
> - Using PTR_ERR_OR_ZERO macro in typec_init().
>
> Changes since v15:
> - "stingification" as proposed by Felipe
> - Checking ARRAY_SIZE in supported_accessory_modes() as proposed by Guenter
>
> Changes since v14:
> - Fixes proposed by Mika
> - "identity" directory for all discover identity VDOs instead of "vdo" attribute
> - alternate mode device names to just "svid-<svid>"
>
> Changes since v13:
> - New API. Everything is registered separately.
>
> Changes since v12:
> - Added prefer_role member to typec_capability structure as requested by Guenter
>
> Changes since v11:
> - The port drivers are responsible of removing the alternate
>   modes (just like the documentation already said).
>
> Changes since v10:
> - Using ATTRIBUTE_GROUPS and DEVICE_ATTR marcos everywhere
> - Moved sysfs_match_string to lib/string.c
> - Rationalized uevents
> - Calling ida_destroy
>
> Changes since v9:
> - Minor typec_wcove.c cleanup as proposed by Guenter Roeck. No
>   function affect.
>
> Changes since v8:
> - checking sysfs_streq() result correctly in sysfs_strmatch
> - fixed accessory check in supported_accessory_mode
> - using "none" as the only string that can clear the preferred role
>
> Changes since v7:
> - Removed "type" attribute from partners
> - Added supports_usb_power_delivery attribute for partner and cable
>
> Changes since v6:
> - current_vconn_role attr renamed to vconn_source (no API changes)
> - Small documentation improvements proposed by Vincent Palatin
>
> Changes since v5:
> - Only updating the roles based on driver notifications
> - Added MODULE_ALIAS for the WhiskeyCove module
> - Including the patch that creates the actual platform device for the
>   WhiskeyCove Type-C PHY in this series.
>
> Changes since v4:
> - Remove the port lock completely
>
> Changes since v3:
> - Documentation cleanup as proposed by Roger Quadros
> - Setting partner altmodes member to NULL on removal and fixing a
>   warning, as proposed by Guenter Roeck
> - Added the following attributes for partners and cables:
>   * supports_usb_power_delivery
>   * id_header_vdo
> - "id_header_vdo" is visible only when the partner or cable supports
>   USB Power Delivery communication.
> - Partner attribute "accessory" is hidden when the partner type is not
>   "Accessory".
>
> Changes since v2:
> - Notification on role and alternate mode changes
> - cleanups
>
> Changes since v1:
> - Completely rewrote alternate mode support
> - Patners, cables and cable plugs presented as devices.
>
>
> Heikki Krogerus (3):
>   lib/string: add sysfs_match_string helper
>   usb: USB Type-C connector class
>   usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY

Just to clarify one thing here: wherever it says "Reviewed-by: Felipe
Balbi..." you could also read "Reviewed-and-Tested-by: Felipe Balbi..."
as I have been running these patches for past few months to test code on
Intel Joule.

-- 
balbi

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-02-21 14:24 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
@ 2017-03-02 15:22   ` Mats Karrman
  2017-03-03  3:13     ` Guenter Roeck
  2017-03-03  3:35   ` Peter Chen
  1 sibling, 1 reply; 64+ messages in thread
From: Mats Karrman @ 2017-03-02 15:22 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb

Hi Heikki,

Good to see things are happening with Type-C!

On 2017-02-21 15:24, Heikki Krogerus wrote:

> ...
> +When connected, the partner will be presented also as its own device under
> +/sys/class/typec/. The parent of the partner device will always be the port it
> +is attached to. The partner attached to port "port0" will be named
> +"port0-partner". Full path to the device would be
> +/sys/class/typec/port0/port0-partner/.

A "/port0" too much?

> +
> +The cable and the two plugs on it may also be optionally presented as their own
> +devices under /sys/class/typec/. The cable attached to the port "port0" port
> +will be named port0-cable and the plug on the SOP Prime end (see USB Power
> +Delivery Specification ch. 2.4) will be named "port0-plug0" and on the SOP
> +Double Prime end "port0-plug1". The parent of a cable will always be the port,
> +and the parent of the cable plugs will always be the cable.
> +
> +If the port, partner or cable plug support Alternate Modes, every supported
> +Alternate Mode SVID will have their own device describing them. The Alternate
> +Modes will not be attached to the typec class. The parent of an alternate mode
> +will be the device that supports it, so for example an alternate mode of
> +port0-partner will bees presented under /sys/class/typec/port0-partner/. Every

bees?

> +mode that is supported will have its own group under the Alternate Mode device
> +named "mode<index>", for example /sys/class/typec/port0/<alternate mode>/mode1/.
> +The requests for entering/exiting a mode can be done with "active" attribute
> +file in that group.
> +
> ...

I'm hoping to find time to upgrade the kernel and try these patches in my system.

Looking forward, one thing I have run into is how to connect the typec driver with a
driver for an alternate mode. E.g. the DisplayPort Alternate Mode specification
includes the HPD (hot plug) and HPD-INT (hot plug interrupt) signals as bits in the
Attention message. These signals are needed by the DisplayPort driver to know when to
start negotiation etc.
Have you got any thoughts on how to standardize such interfaces?

BR // Mats

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-02 15:22   ` Mats Karrman
@ 2017-03-03  3:13     ` Guenter Roeck
  2017-03-03  7:29       ` Mats Karrman
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-03-03  3:13 UTC (permalink / raw)
  To: Mats Karrman, Heikki Krogerus
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 03/02/2017 07:22 AM, Mats Karrman wrote:
> Hi Heikki,
>
> Good to see things are happening with Type-C!
>
> On 2017-02-21 15:24, Heikki Krogerus wrote:
>
>> ...
>> +When connected, the partner will be presented also as its own device under
>> +/sys/class/typec/. The parent of the partner device will always be the port it
>> +is attached to. The partner attached to port "port0" will be named
>> +"port0-partner". Full path to the device would be
>> +/sys/class/typec/port0/port0-partner/.
>
> A "/port0" too much?
>
>> +
>> +The cable and the two plugs on it may also be optionally presented as their own
>> +devices under /sys/class/typec/. The cable attached to the port "port0" port
>> +will be named port0-cable and the plug on the SOP Prime end (see USB Power
>> +Delivery Specification ch. 2.4) will be named "port0-plug0" and on the SOP
>> +Double Prime end "port0-plug1". The parent of a cable will always be the port,
>> +and the parent of the cable plugs will always be the cable.
>> +
>> +If the port, partner or cable plug support Alternate Modes, every supported
>> +Alternate Mode SVID will have their own device describing them. The Alternate
>> +Modes will not be attached to the typec class. The parent of an alternate mode
>> +will be the device that supports it, so for example an alternate mode of
>> +port0-partner will bees presented under /sys/class/typec/port0-partner/. Every
>
> bees?
>
>> +mode that is supported will have its own group under the Alternate Mode device
>> +named "mode<index>", for example /sys/class/typec/port0/<alternate mode>/mode1/.
>> +The requests for entering/exiting a mode can be done with "active" attribute
>> +file in that group.
>> +
>> ...
>
> I'm hoping to find time to upgrade the kernel and try these patches in my system.
>
> Looking forward, one thing I have run into is how to connect the typec driver with a
> driver for an alternate mode. E.g. the DisplayPort Alternate Mode specification
> includes the HPD (hot plug) and HPD-INT (hot plug interrupt) signals as bits in the
> Attention message. These signals are needed by the DisplayPort driver to know when to
> start negotiation etc.
> Have you got any thoughts on how to standardize such interfaces?
>

That really depends on the lower level driver. For Chromebooks, where the Type-C
Protocol Manager runs on the EC, we have an extcon driver which reports the pin states
to the graphics drivers and connects to the Type-C class code using the Type-C class
API. I still need to update, re-test, and publish that code. The published code in
https://chromium.googlesource.com/chromiumos/third_party/kernel/, branch chromeos-4.4,
shows how it can be done, though that code currently still uses the Android Type-C
infrastructure.

Guenter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-02-21 14:24 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
  2017-03-02 15:22   ` Mats Karrman
@ 2017-03-03  3:35   ` Peter Chen
  2017-03-03  4:29     ` Guenter Roeck
  2017-03-03 14:31     ` Heikki Krogerus
  1 sibling, 2 replies; 64+ messages in thread
From: Peter Chen @ 2017-03-03  3:35 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

On Tue, Feb 21, 2017 at 05:24:04PM +0300, Heikki Krogerus wrote:
> +/* --------------------------------------- */
> +/* Driver callbacks to report role updates */
> +
> +/**
> + * typec_set_data_role - Report data role change
> + * @port: The USB Type-C Port where the role was changed
> + * @role: The new data role
> + *
> + * This routine is used by the port drivers to report data role changes.
> + */
> +void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
> +{
> +	if (port->data_role == role)
> +		return;
> +
> +	port->data_role = role;
> +	sysfs_notify(&port->dev.kobj, NULL, "data_role");
> +	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
> +}
> +EXPORT_SYMBOL_GPL(typec_set_data_role);
> +

Hi Keikki,

Have you tested this interface with real dual-role controller/board?
What interface you use when you receive this event to handle
dual-role switch? I am wonder if a common dual-role class is
needed, then we can have a common user utility.

Eg, if "data_role" has changed, the udev can echo "data_role" to
/sys/class/usb-dual-role/role

Maybe we can enhance Roger's drd framework [1] to fulfill that.

[1] https://lwn.net/Articles/682531/
-- 

Best Regards,
Peter Chen

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  3:35   ` Peter Chen
@ 2017-03-03  4:29     ` Guenter Roeck
  2017-03-03  4:52       ` Peter Chen
  2017-03-03 14:31     ` Heikki Krogerus
  1 sibling, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-03-03  4:29 UTC (permalink / raw)
  To: Peter Chen, Heikki Krogerus
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb,
	Roger Quadros, Jun Li

On 03/02/2017 07:35 PM, Peter Chen wrote:
> On Tue, Feb 21, 2017 at 05:24:04PM +0300, Heikki Krogerus wrote:
>> +/* --------------------------------------- */
>> +/* Driver callbacks to report role updates */
>> +
>> +/**
>> + * typec_set_data_role - Report data role change
>> + * @port: The USB Type-C Port where the role was changed
>> + * @role: The new data role
>> + *
>> + * This routine is used by the port drivers to report data role changes.
>> + */
>> +void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
>> +{
>> +	if (port->data_role == role)
>> +		return;
>> +
>> +	port->data_role = role;
>> +	sysfs_notify(&port->dev.kobj, NULL, "data_role");
>> +	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
>> +}
>> +EXPORT_SYMBOL_GPL(typec_set_data_role);
>> +
>
> Hi Keikki,
>
> Have you tested this interface with real dual-role controller/board?

If it helps, my primary test system is a HP Chromebook 13 G1.

> What interface you use when you receive this event to handle
> dual-role switch? I am wonder if a common dual-role class is
> needed, then we can have a common user utility.

I don't really understand "What interface you use when you receive
this event". Can you explain ?

>
> Eg, if "data_role" has changed, the udev can echo "data_role" to
> /sys/class/usb-dual-role/role
>
That sounds like a kernel event delivered to user space via udev or
sysfs notification and returned back into the kernel through a sysfs
attribute. Do I understand that correctly ?

Thanks,
Guenter

> Maybe we can enhance Roger's drd framework [1] to fulfill that.
>
> [1] https://lwn.net/Articles/682531/
>

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  4:29     ` Guenter Roeck
@ 2017-03-03  4:52       ` Peter Chen
  2017-03-03 14:36         ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Peter Chen @ 2017-03-03  4:52 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

On Thu, Mar 02, 2017 at 08:29:07PM -0800, Guenter Roeck wrote:
> On 03/02/2017 07:35 PM, Peter Chen wrote:
> >On Tue, Feb 21, 2017 at 05:24:04PM +0300, Heikki Krogerus wrote:
> >>+/* --------------------------------------- */
> >>+/* Driver callbacks to report role updates */
> >>+
> >>+/**
> >>+ * typec_set_data_role - Report data role change
> >>+ * @port: The USB Type-C Port where the role was changed
> >>+ * @role: The new data role
> >>+ *
> >>+ * This routine is used by the port drivers to report data role changes.
> >>+ */
> >>+void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
> >>+{
> >>+	if (port->data_role == role)
> >>+		return;
> >>+
> >>+	port->data_role = role;
> >>+	sysfs_notify(&port->dev.kobj, NULL, "data_role");
> >>+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
> >>+}
> >>+EXPORT_SYMBOL_GPL(typec_set_data_role);
> >>+
> >
> >Hi Keikki,
> >
> >Have you tested this interface with real dual-role controller/board?
> 
> If it helps, my primary test system is a HP Chromebook 13 G1.
> 
> >What interface you use when you receive this event to handle
> >dual-role switch? I am wonder if a common dual-role class is
> >needed, then we can have a common user utility.
> 
> I don't really understand "What interface you use when you receive
> this event". Can you explain ?
> 

I mean "How to trigger kernel USB controller driver do role switch?"

> >
> >Eg, if "data_role" has changed, the udev can echo "data_role" to
> >/sys/class/usb-dual-role/role
> >
> That sounds like a kernel event delivered to user space via udev or
> sysfs notification and returned back into the kernel through a sysfs
> attribute. Do I understand that correctly ?
> 

Yes.

-- 

Best Regards,
Peter Chen

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  3:13     ` Guenter Roeck
@ 2017-03-03  7:29       ` Mats Karrman
  2017-03-03  9:48         ` Enric Balletbo Serra
                           ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Mats Karrman @ 2017-03-03  7:29 UTC (permalink / raw)
  To: Guenter Roeck, Heikki Krogerus, Greg KH
  Cc: Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 2017-03-03 04:13, Guenter Roeck wrote:

> On 03/02/2017 07:22 AM, Mats Karrman wrote:
>> ....
>> Looking forward, one thing I have run into is how to connect the typec driver with a
>> driver for an alternate mode. E.g. the DisplayPort Alternate Mode specification
>> includes the HPD (hot plug) and HPD-INT (hot plug interrupt) signals as bits in the
>> Attention message. These signals are needed by the DisplayPort driver to know when to
>> start negotiation etc.
>> Have you got any thoughts on how to standardize such interfaces?
> That really depends on the lower level driver. For Chromebooks, where the Type-C
> Protocol Manager runs on the EC, we have an extcon driver which reports the pin states
> to the graphics drivers and connects to the Type-C class code using the Type-C class
> API. I still need to update, re-test, and publish that code. The published code in
> https://chromium.googlesource.com/chromiumos/third_party/kernel/, branch chromeos-4.4,
> shows how it can be done, though that code currently still uses the Android Type-C
> infrastructure.

OK, thanks!

My system is a bit different. It's an i.MX6 SoC with the typec phy and DP controller connected

directly to the SoC and it's using DTB/OF.

Using extcon I would have a driver that is both typec class and extcon driver at the same time

since I can't share the access to the typec phy. Is this done elsewhere in the kernel?

I don't know much about the wcove PMIC and what alternate modes it might support but I

guess that driver would end up in the same place.

Do we need to further standardize attributes under (each) specific alternate mode to

include things such as HPD for the DP mode?

BR // Mats

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  7:29       ` Mats Karrman
@ 2017-03-03  9:48         ` Enric Balletbo Serra
  2017-03-03 12:59         ` Heikki Krogerus
  2017-03-03 14:41         ` Guenter Roeck
  2 siblings, 0 replies; 64+ messages in thread
From: Enric Balletbo Serra @ 2017-03-03  9:48 UTC (permalink / raw)
  To: Mats Karrman
  Cc: Guenter Roeck, Heikki Krogerus, Greg KH, Felipe Balbi,
	Oliver Neukum, linux-kernel, linux-usb

2017-03-03 8:29 GMT+01:00 Mats Karrman <mats.dev.list@gmail.com>:
> On 2017-03-03 04:13, Guenter Roeck wrote:
>
>> On 03/02/2017 07:22 AM, Mats Karrman wrote:
>>>
>>> ....
>>> Looking forward, one thing I have run into is how to connect the typec
>>> driver with a
>>> driver for an alternate mode. E.g. the DisplayPort Alternate Mode
>>> specification
>>> includes the HPD (hot plug) and HPD-INT (hot plug interrupt) signals as
>>> bits in the
>>> Attention message. These signals are needed by the DisplayPort driver to
>>> know when to
>>> start negotiation etc.
>>> Have you got any thoughts on how to standardize such interfaces?
>>
>> That really depends on the lower level driver. For Chromebooks, where the
>> Type-C
>> Protocol Manager runs on the EC, we have an extcon driver which reports
>> the pin states
>> to the graphics drivers and connects to the Type-C class code using the
>> Type-C class
>> API. I still need to update, re-test, and publish that code. The published
>> code in
>> https://chromium.googlesource.com/chromiumos/third_party/kernel/, branch
>> chromeos-4.4,
>> shows how it can be done, though that code currently still uses the
>> Android Type-C
>> infrastructure.
>

On a side note, the cros-ec extcon part for DP is currently discussed
here [1]. This driver works together with the cdn-dp driver that just
landed in mainline. So comments and feedback are welcome

[1] https://lkml.org/lkml/2017/3/1/301

>
> OK, thanks!
>
> My system is a bit different. It's an i.MX6 SoC with the typec phy and DP
> controller connected
>
> directly to the SoC and it's using DTB/OF.
>
> Using extcon I would have a driver that is both typec class and extcon
> driver at the same time
>
> since I can't share the access to the typec phy. Is this done elsewhere in
> the kernel?
>
> I don't know much about the wcove PMIC and what alternate modes it might
> support but I
>
> guess that driver would end up in the same place.
>
> Do we need to further standardize attributes under (each) specific alternate
> mode to
>
> include things such as HPD for the DP mode?
>
> BR // Mats
>

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  7:29       ` Mats Karrman
  2017-03-03  9:48         ` Enric Balletbo Serra
@ 2017-03-03 12:59         ` Heikki Krogerus
  2017-03-03 14:49           ` Guenter Roeck
  2017-03-03 19:27           ` Mats Karrman
  2017-03-03 14:41         ` Guenter Roeck
  2 siblings, 2 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-03 12:59 UTC (permalink / raw)
  To: Mats Karrman, Guenter Roeck
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

Hi,

On Fri, Mar 03, 2017 at 08:29:18AM +0100, Mats Karrman wrote:
> On 2017-03-03 04:13, Guenter Roeck wrote:
> 
> > On 03/02/2017 07:22 AM, Mats Karrman wrote:
> > > ....
> > > Looking forward, one thing I have run into is how to connect the typec driver with a
> > > driver for an alternate mode. E.g. the DisplayPort Alternate Mode specification
> > > includes the HPD (hot plug) and HPD-INT (hot plug interrupt) signals as bits in the
> > > Attention message. These signals are needed by the DisplayPort driver to know when to
> > > start negotiation etc.
> > > Have you got any thoughts on how to standardize such interfaces?

My idea was to have something like the altmode "bus" at one point.
We create a device for every alternate mode registered in typec class,
so the alternate modes registered for the ports and partners would
simply be attached to the altmode bus. There would be a bus per port
of course.

The drivers for the port alternate modes would take care of things
like muxing and other platform specific stuff as needed, and they
would be tied to the underlying subsystems and drivers, graphics in
case of DisplayPort. The drivers for the partner alternate modes would
take care of the actual communication with the alternate mode with
VDMs if needed (but not necessarily), and they would need to be tied
to the port alternate modes. In practice the driver for both the port
and the partner alternate modes will be the same (in the same
location) obviously, at least in most cases.

I think a bus would allow us to support several ways of handling the
alternate modes on different platforms. It would work fine also on
platforms that had no use for it of course, like platforms where
firmware or EC takes care of most things related to Type-C.

But please note that since this is just a high level idea still, we
wouldn't for example need to create an actual bus if there is no use
for it, but since we have the SVIDs that can be used for matching,
then why not try take advantage of them, right.

How would something like that sound to you guys?

> > That really depends on the lower level driver. For Chromebooks, where the Type-C
> > Protocol Manager runs on the EC, we have an extcon driver which reports the pin states
> > to the graphics drivers and connects to the Type-C class code using the Type-C class
> > API. I still need to update, re-test, and publish that code. The published code in
> > https://chromium.googlesource.com/chromiumos/third_party/kernel/, branch chromeos-4.4,
> > shows how it can be done, though that code currently still uses the Android Type-C
> > infrastructure.

In this case I think you would only need to register a driver with the
bus in case you want the handle to the device for the alternate mode.

> OK, thanks!
> 
> My system is a bit different. It's an i.MX6 SoC with the typec phy and DP controller connected
> directly to the SoC and it's using DTB/OF.

Is this "DP controller" a controller that is capable of taking care of
the USB Power Delivery communication with the partner regarding
DisplayPort alternate mode?

> Using extcon I would have a driver that is both typec class and extcon driver at the same time
> since I can't share the access to the typec phy. Is this done elsewhere in the kernel?
> I don't know much about the wcove PMIC and what alternate modes it might support but I
> guess that driver would end up in the same place.

What alternate modes systems with WhiskeyCove supports depends on
the platform. WhiskeyCove PMIC (as in Power Management IC) is
available on a few Intel Atom platforms. The USB Type-C PHY in it
provides a simple USB PD transceiver that does not touch the actual
communication with the partners. The communication needs to be done in
software, including dealing with alternate modes.

I'm not planning on using extcon for anything with WhiskeyCove. I
don't have any use for it. It looks to me that extcon is used just as
a tool to create software couplings in many cases, and I'm not
completely comfortable with that.

In my case with DP altmode, if we had for example muxes to take care
of, I don't think it would be a problem to tie the driver for the mux
to the graphics directly, so basically make it part of the graphics
stack. That driver would be the port (and partner) altmode driver.

> Do we need to further standardize attributes under (each) specific alternate mode to
> include things such as HPD for the DP mode?

I'm not completely sure what kind of system you have, but I would
imagine that if we had the bus, your DP controller driver would be the
port (and partner) alternate mode driver. The bus would bind you to
the typec phy.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  3:35   ` Peter Chen
  2017-03-03  4:29     ` Guenter Roeck
@ 2017-03-03 14:31     ` Heikki Krogerus
  2017-03-06  1:15       ` Peter Chen
  1 sibling, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-03 14:31 UTC (permalink / raw)
  To: Peter Chen
  Cc: Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

Hi Peter,

On Fri, Mar 03, 2017 at 11:35:29AM +0800, Peter Chen wrote:
> On Tue, Feb 21, 2017 at 05:24:04PM +0300, Heikki Krogerus wrote:
> > +/* --------------------------------------- */
> > +/* Driver callbacks to report role updates */
> > +
> > +/**
> > + * typec_set_data_role - Report data role change
> > + * @port: The USB Type-C Port where the role was changed
> > + * @role: The new data role
> > + *
> > + * This routine is used by the port drivers to report data role changes.
> > + */
> > +void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
> > +{
> > +	if (port->data_role == role)
> > +		return;
> > +
> > +	port->data_role = role;
> > +	sysfs_notify(&port->dev.kobj, NULL, "data_role");
> > +	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
> > +}
> > +EXPORT_SYMBOL_GPL(typec_set_data_role);
> > +
> 
> Hi Keikki,
> 
> Have you tested this interface with real dual-role controller/board?

Yes. Our boards are mostly USB dual-role capable.

> What interface you use when you receive this event to handle
> dual-role switch? I am wonder if a common dual-role class is
> needed, then we can have a common user utility.
> 
> Eg, if "data_role" has changed, the udev can echo "data_role" to
> /sys/class/usb-dual-role/role

No. If the partner executes successfully for example DR_Swap message,
the kernel has to take care everything that is needed for the role to
be what ever was negotiated on its own. User space can't be involved
with that.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  4:52       ` Peter Chen
@ 2017-03-03 14:36         ` Guenter Roeck
  2017-03-06  1:24           ` Peter Chen
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-03-03 14:36 UTC (permalink / raw)
  To: Peter Chen
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

On 03/02/2017 08:52 PM, Peter Chen wrote:
> On Thu, Mar 02, 2017 at 08:29:07PM -0800, Guenter Roeck wrote:
>> On 03/02/2017 07:35 PM, Peter Chen wrote:
>>> On Tue, Feb 21, 2017 at 05:24:04PM +0300, Heikki Krogerus wrote:
>>>> +/* --------------------------------------- */
>>>> +/* Driver callbacks to report role updates */
>>>> +
>>>> +/**
>>>> + * typec_set_data_role - Report data role change
>>>> + * @port: The USB Type-C Port where the role was changed
>>>> + * @role: The new data role
>>>> + *
>>>> + * This routine is used by the port drivers to report data role changes.
>>>> + */
>>>> +void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
>>>> +{
>>>> +	if (port->data_role == role)
>>>> +		return;
>>>> +
>>>> +	port->data_role = role;
>>>> +	sysfs_notify(&port->dev.kobj, NULL, "data_role");
>>>> +	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(typec_set_data_role);
>>>> +
>>>
>>> Hi Keikki,
>>>
>>> Have you tested this interface with real dual-role controller/board?
>>
>> If it helps, my primary test system is a HP Chromebook 13 G1.
>>
>>> What interface you use when you receive this event to handle
>>> dual-role switch? I am wonder if a common dual-role class is
>>> needed, then we can have a common user utility.
>>
>> I don't really understand "What interface you use when you receive
>> this event". Can you explain ?
>>
>
> I mean "How to trigger kernel USB controller driver do role switch?"
>

I think this should be handled by the lower level driver. I am wide open
to other ideas, though.

>>>
>>> Eg, if "data_role" has changed, the udev can echo "data_role" to
>>> /sys/class/usb-dual-role/role
>>>
>> That sounds like a kernel event delivered to user space via udev or
>> sysfs notification and returned back into the kernel through a sysfs
>> attribute. Do I understand that correctly ?
>>
>
> Yes.
>

That doesn't sound like a good idea to me, and I don't see a technical reason
to require it.

Thanks,
Guenter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03  7:29       ` Mats Karrman
  2017-03-03  9:48         ` Enric Balletbo Serra
  2017-03-03 12:59         ` Heikki Krogerus
@ 2017-03-03 14:41         ` Guenter Roeck
  2 siblings, 0 replies; 64+ messages in thread
From: Guenter Roeck @ 2017-03-03 14:41 UTC (permalink / raw)
  To: Mats Karrman, Heikki Krogerus, Greg KH
  Cc: Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 03/02/2017 11:29 PM, Mats Karrman wrote:
> On 2017-03-03 04:13, Guenter Roeck wrote:
>
>> On 03/02/2017 07:22 AM, Mats Karrman wrote:
>>> ....
>>> Looking forward, one thing I have run into is how to connect the typec driver with a
>>> driver for an alternate mode. E.g. the DisplayPort Alternate Mode specification
>>> includes the HPD (hot plug) and HPD-INT (hot plug interrupt) signals as bits in the
>>> Attention message. These signals are needed by the DisplayPort driver to know when to
>>> start negotiation etc.
>>> Have you got any thoughts on how to standardize such interfaces?
>> That really depends on the lower level driver. For Chromebooks, where the Type-C
>> Protocol Manager runs on the EC, we have an extcon driver which reports the pin states
>> to the graphics drivers and connects to the Type-C class code using the Type-C class
>> API. I still need to update, re-test, and publish that code. The published code in
>> https://chromium.googlesource.com/chromiumos/third_party/kernel/, branch chromeos-4.4,
>> shows how it can be done, though that code currently still uses the Android Type-C
>> infrastructure.
>
> OK, thanks!
>
> My system is a bit different. It's an i.MX6 SoC with the typec phy and DP controller connected
>
> directly to the SoC and it's using DTB/OF.
>

Sounds quite similar to rk3399 (Samsung Chromebook Plus). I have not ported the Type-C class code
to that system yet, but it does use the extcon cros_ec driver, and DP connectivity is signaled
to the DP code through extcon events.

> Using extcon I would have a driver that is both typec class and extcon driver at the same time
>
> since I can't share the access to the typec phy. Is this done elsewhere in the kernel?
>
See above. The code is available in the repository mentioned above.

Guenter

> I don't know much about the wcove PMIC and what alternate modes it might support but I
>
> guess that driver would end up in the same place.
>
> Do we need to further standardize attributes under (each) specific alternate mode to
>
> include things such as HPD for the DP mode?
>
> BR // Mats
>
>

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03 12:59         ` Heikki Krogerus
@ 2017-03-03 14:49           ` Guenter Roeck
  2017-03-03 19:27           ` Mats Karrman
  1 sibling, 0 replies; 64+ messages in thread
From: Guenter Roeck @ 2017-03-03 14:49 UTC (permalink / raw)
  To: Heikki Krogerus, Mats Karrman
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 03/03/2017 04:59 AM, Heikki Krogerus wrote:
> Hi,
>
> On Fri, Mar 03, 2017 at 08:29:18AM +0100, Mats Karrman wrote:
>> On 2017-03-03 04:13, Guenter Roeck wrote:
>>
>>> On 03/02/2017 07:22 AM, Mats Karrman wrote:
>>>> ....
>>>> Looking forward, one thing I have run into is how to connect the typec driver with a
>>>> driver for an alternate mode. E.g. the DisplayPort Alternate Mode specification
>>>> includes the HPD (hot plug) and HPD-INT (hot plug interrupt) signals as bits in the
>>>> Attention message. These signals are needed by the DisplayPort driver to know when to
>>>> start negotiation etc.
>>>> Have you got any thoughts on how to standardize such interfaces?
>
> My idea was to have something like the altmode "bus" at one point.
> We create a device for every alternate mode registered in typec class,
> so the alternate modes registered for the ports and partners would
> simply be attached to the altmode bus. There would be a bus per port
> of course.
>
> The drivers for the port alternate modes would take care of things
> like muxing and other platform specific stuff as needed, and they
> would be tied to the underlying subsystems and drivers, graphics in
> case of DisplayPort. The drivers for the partner alternate modes would
> take care of the actual communication with the alternate mode with
> VDMs if needed (but not necessarily), and they would need to be tied
> to the port alternate modes. In practice the driver for both the port
> and the partner alternate modes will be the same (in the same
> location) obviously, at least in most cases.
>
> I think a bus would allow us to support several ways of handling the
> alternate modes on different platforms. It would work fine also on
> platforms that had no use for it of course, like platforms where
> firmware or EC takes care of most things related to Type-C.
>
> But please note that since this is just a high level idea still, we
> wouldn't for example need to create an actual bus if there is no use
> for it, but since we have the SVIDs that can be used for matching,
> then why not try take advantage of them, right.
>
> How would something like that sound to you guys?
>
>>> That really depends on the lower level driver. For Chromebooks, where the Type-C
>>> Protocol Manager runs on the EC, we have an extcon driver which reports the pin states
>>> to the graphics drivers and connects to the Type-C class code using the Type-C class
>>> API. I still need to update, re-test, and publish that code. The published code in
>>> https://chromium.googlesource.com/chromiumos/third_party/kernel/, branch chromeos-4.4,
>>> shows how it can be done, though that code currently still uses the Android Type-C
>>> infrastructure.
>
> In this case I think you would only need to register a driver with the
> bus in case you want the handle to the device for the alternate mode.
>
>> OK, thanks!
>>
>> My system is a bit different. It's an i.MX6 SoC with the typec phy and DP controller connected
>> directly to the SoC and it's using DTB/OF.
>
> Is this "DP controller" a controller that is capable of taking care of
> the USB Power Delivery communication with the partner regarding
> DisplayPort alternate mode?
>
>> Using extcon I would have a driver that is both typec class and extcon driver at the same time
>> since I can't share the access to the typec phy. Is this done elsewhere in the kernel?
>> I don't know much about the wcove PMIC and what alternate modes it might support but I
>> guess that driver would end up in the same place.
>
> What alternate modes systems with WhiskeyCove supports depends on
> the platform. WhiskeyCove PMIC (as in Power Management IC) is
> available on a few Intel Atom platforms. The USB Type-C PHY in it
> provides a simple USB PD transceiver that does not touch the actual
> communication with the partners. The communication needs to be done in
> software, including dealing with alternate modes.
>
> I'm not planning on using extcon for anything with WhiskeyCove. I
> don't have any use for it. It looks to me that extcon is used just as
> a tool to create software couplings in many cases, and I'm not
> completely comfortable with that.
>

For rk3399 we went back and forth trying other approaches, but using extcon
turned out to be the most straightforward mechanism; everything else would
just have replicated what extcon already provides. Having said that,
I am open to other approaches. The rk3399 implementation may be seen as an
example on what is required, specifically when it comes to the interaction
between cable, DP, and the Type-C phy.

Guenter

> In my case with DP altmode, if we had for example muxes to take care
> of, I don't think it would be a problem to tie the driver for the mux
> to the graphics directly, so basically make it part of the graphics
> stack. That driver would be the port (and partner) altmode driver.
>
>> Do we need to further standardize attributes under (each) specific alternate mode to
>> include things such as HPD for the DP mode?
>
> I'm not completely sure what kind of system you have, but I would
> imagine that if we had the bus, your DP controller driver would be the
> port (and partner) alternate mode driver. The bus would bind you to
> the typec phy.
>
>
> Thanks,
>

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03 12:59         ` Heikki Krogerus
  2017-03-03 14:49           ` Guenter Roeck
@ 2017-03-03 19:27           ` Mats Karrman
  2017-03-06  9:37             ` Oliver Neukum
  2017-03-06 13:14             ` Heikki Krogerus
  1 sibling, 2 replies; 64+ messages in thread
From: Mats Karrman @ 2017-03-03 19:27 UTC (permalink / raw)
  To: Heikki Krogerus, Guenter Roeck
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 2017-03-03 13:59, Heikki Krogerus wrote:

> On Fri, Mar 03, 2017 at 08:29:18AM +0100, Mats Karrman wrote:
> ....

> How would something like that sound to you guys?

Complicated... Need to marinate on that for a while ;)

>> My system is a bit different. It's an i.MX6 SoC with the typec phy and DP controller connected
>> directly to the SoC and it's using DTB/OF.
> Is this "DP controller" a controller that is capable of taking care of
> the USB Power Delivery communication with the partner regarding
> DisplayPort alternate mode?

No, the "DP controller" just talks DP and knows nothing about Type-C or USB PD.
It takes a video stream from the SoC and turns it into a DP link, set up and orchestrated
by the corresponding driver. And all the driver needs from Type-C is the plugged in / interrupt /
plugged out events.

The analog switching between USB / safe / DP signal levels in the Type-C connector is, I think,
best handled by the software doing the USB PD negotiation / Altmode handling (using some GPIOs).

>> Do we need to further standardize attributes under (each) specific alternate mode to
>> include things such as HPD for the DP mode?
> I'm not completely sure what kind of system you have, but I would
> imagine that if we had the bus, your DP controller driver would be the
> port (and partner) alternate mode driver. The bus would bind you to
> the typec phy.

So, both the DP controller and the USB PD phy are I2C devices, and now I have to make them both
attach to the AM bus as well?

BR,
Mats

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03 14:31     ` Heikki Krogerus
@ 2017-03-06  1:15       ` Peter Chen
  2017-03-06 13:16         ` Heikki Krogerus
  0 siblings, 1 reply; 64+ messages in thread
From: Peter Chen @ 2017-03-06  1:15 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

On Fri, Mar 03, 2017 at 04:31:33PM +0200, Heikki Krogerus wrote:
> Hi Peter,
> 
> On Fri, Mar 03, 2017 at 11:35:29AM +0800, Peter Chen wrote:
> > On Tue, Feb 21, 2017 at 05:24:04PM +0300, Heikki Krogerus wrote:
> > > +/* --------------------------------------- */
> > > +/* Driver callbacks to report role updates */
> > > +
> > > +/**
> > > + * typec_set_data_role - Report data role change
> > > + * @port: The USB Type-C Port where the role was changed
> > > + * @role: The new data role
> > > + *
> > > + * This routine is used by the port drivers to report data role changes.
> > > + */
> > > +void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
> > > +{
> > > +	if (port->data_role == role)
> > > +		return;
> > > +
> > > +	port->data_role = role;
> > > +	sysfs_notify(&port->dev.kobj, NULL, "data_role");
> > > +	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
> > > +}
> > > +EXPORT_SYMBOL_GPL(typec_set_data_role);
> > > +
> > 
> > Hi Keikki,
> > 
> > Have you tested this interface with real dual-role controller/board?
> 
> Yes. Our boards are mostly USB dual-role capable.
> 
> > What interface you use when you receive this event to handle
> > dual-role switch? I am wonder if a common dual-role class is
> > needed, then we can have a common user utility.
> > 
> > Eg, if "data_role" has changed, the udev can echo "data_role" to
> > /sys/class/usb-dual-role/role
> 
> No. If the partner executes successfully for example DR_Swap message,
> the kernel has to take care everything that is needed for the role to
> be what ever was negotiated on its own. User space can't be involved
> with that.
> 

Would you give me an example how kernel handle this? How type-C event
triggers role switch?

-- 

Best Regards,
Peter Chen

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03 14:36         ` Guenter Roeck
@ 2017-03-06  1:24           ` Peter Chen
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Chen @ 2017-03-06  1:24 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

On Fri, Mar 03, 2017 at 06:36:50AM -0800, Guenter Roeck wrote:
> On 03/02/2017 08:52 PM, Peter Chen wrote:
> >On Thu, Mar 02, 2017 at 08:29:07PM -0800, Guenter Roeck wrote:
> >>On 03/02/2017 07:35 PM, Peter Chen wrote:
> >>>On Tue, Feb 21, 2017 at 05:24:04PM +0300, Heikki Krogerus wrote:
> >>>>+/* --------------------------------------- */
> >>>>+/* Driver callbacks to report role updates */
> >>>>+
> >>>>+/**
> >>>>+ * typec_set_data_role - Report data role change
> >>>>+ * @port: The USB Type-C Port where the role was changed
> >>>>+ * @role: The new data role
> >>>>+ *
> >>>>+ * This routine is used by the port drivers to report data role changes.
> >>>>+ */
> >>>>+void typec_set_data_role(struct typec_port *port, enum typec_data_role role)
> >>>>+{
> >>>>+	if (port->data_role == role)
> >>>>+		return;
> >>>>+
> >>>>+	port->data_role = role;
> >>>>+	sysfs_notify(&port->dev.kobj, NULL, "data_role");
> >>>>+	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
> >>>>+}
> >>>>+EXPORT_SYMBOL_GPL(typec_set_data_role);
> >>>>+
> >>>
> >>>Hi Keikki,
> >>>
> >>>Have you tested this interface with real dual-role controller/board?
> >>
> >>If it helps, my primary test system is a HP Chromebook 13 G1.
> >>
> >>>What interface you use when you receive this event to handle
> >>>dual-role switch? I am wonder if a common dual-role class is
> >>>needed, then we can have a common user utility.
> >>
> >>I don't really understand "What interface you use when you receive
> >>this event". Can you explain ?
> >>
> >
> >I mean "How to trigger kernel USB controller driver do role switch?"
> >
> 
> I think this should be handled by the lower level driver. I am wide open
> to other ideas, though.
> 

Would you show me how it works at your test system if it is not
a private thing?

> >>>
> >>>Eg, if "data_role" has changed, the udev can echo "data_role" to
> >>>/sys/class/usb-dual-role/role
> >>>
> >>That sounds like a kernel event delivered to user space via udev or
> >>sysfs notification and returned back into the kernel through a sysfs
> >>attribute. Do I understand that correctly ?
> >>
> >
> >Yes.
> >
> 
> That doesn't sound like a good idea to me, and I don't see a technical reason
> to require it.
> 

I don't like it either, but current kernel has no ability to handle it
except you use hardware signal like extcon-gpio or controller id as
input pin to SoC handle this event.

-- 

Best Regards,
Peter Chen

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03 19:27           ` Mats Karrman
@ 2017-03-06  9:37             ` Oliver Neukum
  2017-03-06 13:14             ` Heikki Krogerus
  1 sibling, 0 replies; 64+ messages in thread
From: Oliver Neukum @ 2017-03-06  9:37 UTC (permalink / raw)
  To: Mats Karrman, Heikki Krogerus, Guenter Roeck
  Cc: Felipe Balbi, Greg KH, linux-kernel, linux-usb

Am Freitag, den 03.03.2017, 20:27 +0100 schrieb Mats Karrman:
> On 2017-03-03 13:59, Heikki Krogerus wrote:
> 
> > 
> > On Fri, Mar 03, 2017 at 08:29:18AM +0100, Mats Karrman wrote:
> > ....
> 
> > 
> > How would something like that sound to you guys?
> 
> Complicated... Need to marinate on that for a while ;)

The thing is that a type C plug has operations that affect every
device on it and need to be synchronized. Reset and power
requirements would be the obvious examples.

It seems to me that the natural way to represent this is a bus.
Like SCSI where you have a bus reset operation.

	Regards
		Oliver

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-03 19:27           ` Mats Karrman
  2017-03-06  9:37             ` Oliver Neukum
@ 2017-03-06 13:14             ` Heikki Krogerus
  2017-03-07 22:30               ` Mats Karrman
  1 sibling, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-06 13:14 UTC (permalink / raw)
  To: Mats Karrman
  Cc: Guenter Roeck, Greg KH, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb

Hi Mats,

On Fri, Mar 03, 2017 at 08:27:08PM +0100, Mats Karrman wrote:
> On 2017-03-03 13:59, Heikki Krogerus wrote:
> 
> > On Fri, Mar 03, 2017 at 08:29:18AM +0100, Mats Karrman wrote:
> > ....
> 
> > How would something like that sound to you guys?
> 
> Complicated... Need to marinate on that for a while ;)

Sorry about the bad explanation :-). Let me try again..  I'm simply
looking for a method that is as scalable as possible to handle the
alternate modes, basically how to couple the different components
involved. Bus would feel like the best approach at the moment.

> > > My system is a bit different. It's an i.MX6 SoC with the typec phy and DP controller connected
> > > directly to the SoC and it's using DTB/OF.
> > Is this "DP controller" a controller that is capable of taking care of
> > the USB Power Delivery communication with the partner regarding
> > DisplayPort alternate mode?
> 
> No, the "DP controller" just talks DP and knows nothing about Type-C or USB PD.
> It takes a video stream from the SoC and turns it into a DP link, set up and orchestrated
> by the corresponding driver. And all the driver needs from Type-C is the plugged in / interrupt /
> plugged out events.

Got it.

> The analog switching between USB / safe / DP signal levels in the Type-C connector is, I think,
> best handled by the software doing the USB PD negotiation / Altmode handling (using some GPIOs).
> 
> > > Do we need to further standardize attributes under (each) specific alternate mode to
> > > include things such as HPD for the DP mode?
> > I'm not completely sure what kind of system you have, but I would
> > imagine that if we had the bus, your DP controller driver would be the
> > port (and partner) alternate mode driver. The bus would bind you to
> > the typec phy.
> 
> So, both the DP controller and the USB PD phy are I2C devices, and now I have to make them both
> attach to the AM bus as well?

The DP controller would provide the driver and the USB PD phy
(actually, the typec class) the device.

Would it be a problem to register these I2C devices with some other
subsystem, was it extcon or something like AM bus? It really would not
be that uncommon. Or have I misunderstood your question?


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-06  1:15       ` Peter Chen
@ 2017-03-06 13:16         ` Heikki Krogerus
  2017-03-07  1:36           ` Peter Chen
  0 siblings, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-06 13:16 UTC (permalink / raw)
  To: Peter Chen
  Cc: Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

Hi Peter,

On Mon, Mar 06, 2017 at 09:15:51AM +0800, Peter Chen wrote:
> > > What interface you use when you receive this event to handle
> > > dual-role switch? I am wonder if a common dual-role class is
> > > needed, then we can have a common user utility.
> > > 
> > > Eg, if "data_role" has changed, the udev can echo "data_role" to
> > > /sys/class/usb-dual-role/role
> > 
> > No. If the partner executes successfully for example DR_Swap message,
> > the kernel has to take care everything that is needed for the role to
> > be what ever was negotiated on its own. User space can't be involved
> > with that.
> > 
> 
> Would you give me an example how kernel handle this? How type-C event
> triggers role switch?

On our boards, the firmware or EC (or ACPI) configures the hardware as
needed and also notifies the components using ACPI if needed. It's
often not even possible to directly configure the components/hardware
for a particular role.

I'm not commenting on Roger's dual role patch series, but I don't
really think it should be mixed with Type-C. USB Type-C and USB Power
Delivery define their own ways of handling the roles, and they are not
limited to the data role only. Things like OTG for example will, and
actually can not be supported. With Type-C we will have competing
state machines compared to OTG. The dual-role framework may be useful
on systems that provide more traditional connectors, which possibly
have the ID-pin like micro-AB, and possibly also support OTG. It can
also be something that exist in parallel with the Type-C class, but
there just can not be any dependencies between the two.


Thanks,

-- 
heikki

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

* RE: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-06 13:16         ` Heikki Krogerus
@ 2017-03-07  1:36           ` Peter Chen
  2017-03-07  8:57             ` Heikki Krogerus
  0 siblings, 1 reply; 64+ messages in thread
From: Peter Chen @ 2017-03-07  1:36 UTC (permalink / raw)
  To: Heikki Krogerus, Peter Chen
  Cc: Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

 
>
>On Mon, Mar 06, 2017 at 09:15:51AM +0800, Peter Chen wrote:
>> > > What interface you use when you receive this event to handle
>> > > dual-role switch? I am wonder if a common dual-role class is
>> > > needed, then we can have a common user utility.
>> > >
>> > > Eg, if "data_role" has changed, the udev can echo "data_role" to
>> > > /sys/class/usb-dual-role/role
>> >
>> > No. If the partner executes successfully for example DR_Swap
>> > message, the kernel has to take care everything that is needed for
>> > the role to be what ever was negotiated on its own. User space can't
>> > be involved with that.
>> >
>>
>> Would you give me an example how kernel handle this? How type-C event
>> triggers role switch?
>
>On our boards, the firmware or EC (or ACPI) configures the hardware as needed
>and also notifies the components using ACPI if needed. It's often not even possible to
>directly configure the components/hardware for a particular role.
>

You mean type-C trigger an ACPI event, and this ACPI event can notify related
USB controller driver doing role switch? If it is correct, there is a notifier between type-C
and USB controller driver, how to define this notifier for non-ACPI platform? 

>I'm not commenting on Roger's dual role patch series, but I don't really think it should
>be mixed with Type-C. USB Type-C and USB Power Delivery define their own ways
>of handling the roles, and they are not limited to the data role only. Things like OTG
>for example will, and actually can not be supported. With Type-C we will have
>competing state machines compared to OTG. The dual-role framework may be
>useful on systems that provide more traditional connectors, which possibly have the
>ID-pin like micro-AB, and possibly also support OTG. It can also be something that
>exist in parallel with the Type-C class, but there just can not be any dependencies
>between the two.
>

Yes, there are two independent things. But if the kernel doesn't have a notifier between
type-C message sender (type-c class) and message receiver (like USB controller driver
for role switch or other drivers for alternate mode message), we had to find some ways at
userspace.

Peter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-07  1:36           ` Peter Chen
@ 2017-03-07  8:57             ` Heikki Krogerus
  2017-03-08  1:53               ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-07  8:57 UTC (permalink / raw)
  To: Peter Chen
  Cc: Peter Chen, Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb, Roger Quadros, Jun Li

On Tue, Mar 07, 2017 at 01:36:29AM +0000, Peter Chen wrote:
> >On Mon, Mar 06, 2017 at 09:15:51AM +0800, Peter Chen wrote:
> >> > > What interface you use when you receive this event to handle
> >> > > dual-role switch? I am wonder if a common dual-role class is
> >> > > needed, then we can have a common user utility.
> >> > >
> >> > > Eg, if "data_role" has changed, the udev can echo "data_role" to
> >> > > /sys/class/usb-dual-role/role
> >> >
> >> > No. If the partner executes successfully for example DR_Swap
> >> > message, the kernel has to take care everything that is needed for
> >> > the role to be what ever was negotiated on its own. User space can't
> >> > be involved with that.
> >> >
> >>
> >> Would you give me an example how kernel handle this? How type-C event
> >> triggers role switch?
> >
> >On our boards, the firmware or EC (or ACPI) configures the hardware as needed
> >and also notifies the components using ACPI if needed. It's often not even possible to
> >directly configure the components/hardware for a particular role.
> >
> 
> You mean type-C trigger an ACPI event, and this ACPI event can notify related
> USB controller driver doing role switch?

No (firmware programs the dual-role hw/registers), but never mind.
That could be the case.

> If it is correct, there is a notifier between type-C
> and USB controller driver, how to define this notifier for non-ACPI platform? 

Once there is a platform with Type-C like that, the problem needs to
be solved. However..

> >I'm not commenting on Roger's dual role patch series, but I don't really think it should
> >be mixed with Type-C. USB Type-C and USB Power Delivery define their own ways
> >of handling the roles, and they are not limited to the data role only. Things like OTG
> >for example will, and actually can not be supported. With Type-C we will have
> >competing state machines compared to OTG. The dual-role framework may be
> >useful on systems that provide more traditional connectors, which possibly have the
> >ID-pin like micro-AB, and possibly also support OTG. It can also be something that
> >exist in parallel with the Type-C class, but there just can not be any dependencies
> >between the two.
> >
> 
> Yes, there are two independent things. But if the kernel doesn't have a notifier between
> type-C message sender (type-c class) and message receiver (like USB controller driver
> for role switch or other drivers for alternate mode message), we had to find some ways at
> userspace.

..what ever the solution is, it really can't rely on user space.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-06 13:14             ` Heikki Krogerus
@ 2017-03-07 22:30               ` Mats Karrman
  2017-03-08  1:38                 ` Guenter Roeck
  2017-03-08 13:58                 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
  0 siblings, 2 replies; 64+ messages in thread
From: Mats Karrman @ 2017-03-07 22:30 UTC (permalink / raw)
  To: Heikki Krogerus, Guenter Roeck
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 2017-03-06 14:14, Heikki Krogerus wrote:

> Hi Mats,
>
> On Fri, Mar 03, 2017 at 08:27:08PM +0100, Mats Karrman wrote:
>>>> My system is a bit different. It's an i.MX6 SoC with the typec phy and DP controller connected
>>>> directly to the SoC and it's using DTB/OF.
>>> Is this "DP controller" a controller that is capable of taking care of
>>> the USB Power Delivery communication with the partner regarding
>>> DisplayPort alternate mode?
>> No, the "DP controller" just talks DP and knows nothing about Type-C or USB PD.
>> It takes a video stream from the SoC and turns it into a DP link, set up and orchestrated
>> by the corresponding driver. And all the driver needs from Type-C is the plugged in / interrupt /
>> plugged out events.
> Got it.
>
>> The analog switching between USB / safe / DP signal levels in the Type-C connector is, I think,
>> best handled by the software doing the USB PD negotiation / Altmode handling (using some GPIOs).
>>
>>>> Do we need to further standardize attributes under (each) specific alternate mode to
>>>> include things such as HPD for the DP mode?
>>> I'm not completely sure what kind of system you have, but I would
>>> imagine that if we had the bus, your DP controller driver would be the
>>> port (and partner) alternate mode driver. The bus would bind you to
>>> the typec phy.
>> So, both the DP controller and the USB PD phy are I2C devices, and now I have to make them both
>> attach to the AM bus as well?
> The DP controller would provide the driver and the USB PD phy
> (actually, the typec class) the device.
>
> Would it be a problem to register these I2C devices with some other
> subsystem, was it extcon or something like AM bus? It really would not
> be that uncommon. Or have I misunderstood your question?

OK, so a bus could be used for drivers to find each other but it still does not say
anything about how those drivers are supposed to communicate so that must be prescribed
separately, right?

If I read Heikki's original suggestion I understand it like the DP driver would be
responsible for AM specific USB PD/VDM communication. But wouldn't that lead
to a lot of code duplication since the AM protocol is the same for all drivers of
a kind?

I'm still struggling to catch up on what you guys have been up to during the
last year or so :-) and came across some patches of Guenter from last October:

http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1243527.html

What happened to them? Has there been any progress since then?

BR // Mats

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-07 22:30               ` Mats Karrman
@ 2017-03-08  1:38                 ` Guenter Roeck
  2017-04-08 23:09                   ` USB Type-C Port Manager API concern Mats Karrman
  2017-03-08 13:58                 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
  1 sibling, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-03-08  1:38 UTC (permalink / raw)
  To: Mats Karrman, Heikki Krogerus
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 03/07/2017 02:30 PM, Mats Karrman wrote:
[ ... ]

>
> I'm still struggling to catch up on what you guys have been up to during the
> last year or so :-) and came across some patches of Guenter from last October:
>
> http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1243527.html
>
> What happened to them? Has there been any progress since then?
>

Updates to keep in sync with API changes, bug fixes, and minor improvements,
for the most part. I can post a current version if there is interest.
The latest version is also available from
https://chromium-review.googlesource.com/#/c/389917/

Guenter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-07  8:57             ` Heikki Krogerus
@ 2017-03-08  1:53               ` Guenter Roeck
  2017-03-08  6:50                 ` Peter Chen
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-03-08  1:53 UTC (permalink / raw)
  To: Heikki Krogerus, Peter Chen
  Cc: Peter Chen, Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel,
	linux-usb, Roger Quadros, Jun Li

On 03/07/2017 12:57 AM, Heikki Krogerus wrote:
> On Tue, Mar 07, 2017 at 01:36:29AM +0000, Peter Chen wrote:
>>> On Mon, Mar 06, 2017 at 09:15:51AM +0800, Peter Chen wrote:
>>>>>> What interface you use when you receive this event to handle
>>>>>> dual-role switch? I am wonder if a common dual-role class is
>>>>>> needed, then we can have a common user utility.
>>>>>>
>>>>>> Eg, if "data_role" has changed, the udev can echo "data_role" to
>>>>>> /sys/class/usb-dual-role/role
>>>>>
>>>>> No. If the partner executes successfully for example DR_Swap
>>>>> message, the kernel has to take care everything that is needed for
>>>>> the role to be what ever was negotiated on its own. User space can't
>>>>> be involved with that.
>>>>>
>>>>
>>>> Would you give me an example how kernel handle this? How type-C event
>>>> triggers role switch?
>>>
>>> On our boards, the firmware or EC (or ACPI) configures the hardware as needed
>>> and also notifies the components using ACPI if needed. It's often not even possible to
>>> directly configure the components/hardware for a particular role.
>>>
>>
>> You mean type-C trigger an ACPI event, and this ACPI event can notify related
>> USB controller driver doing role switch?
>
> No (firmware programs the dual-role hw/registers), but never mind.
> That could be the case.
>
>> If it is correct, there is a notifier between type-C
>> and USB controller driver, how to define this notifier for non-ACPI platform?
>
> Once there is a platform with Type-C like that, the problem needs to
> be solved. However..
>
>>> I'm not commenting on Roger's dual role patch series, but I don't really think it should
>>> be mixed with Type-C. USB Type-C and USB Power Delivery define their own ways
>>> of handling the roles, and they are not limited to the data role only. Things like OTG
>>> for example will, and actually can not be supported. With Type-C we will have
>>> competing state machines compared to OTG. The dual-role framework may be
>>> useful on systems that provide more traditional connectors, which possibly have the
>>> ID-pin like micro-AB, and possibly also support OTG. It can also be something that
>>> exist in parallel with the Type-C class, but there just can not be any dependencies
>>> between the two.
>>>
>>
>> Yes, there are two independent things. But if the kernel doesn't have a notifier between
>> type-C message sender (type-c class) and message receiver (like USB controller driver
>> for role switch or other drivers for alternate mode message), we had to find some ways at
>> userspace.
>
> ..what ever the solution is, it really can't rely on user space.
>

... and, at least for our application, using extcon for the necessary notifications
works just fine.

Guenter

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

* RE: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-08  1:53               ` Guenter Roeck
@ 2017-03-08  6:50                 ` Peter Chen
  2017-03-08 14:44                   ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Peter Chen @ 2017-03-08  6:50 UTC (permalink / raw)
  To: Guenter Roeck, Heikki Krogerus
  Cc: Peter Chen, Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel,
	linux-usb, Roger Quadros, Jun Li

 
>>> You mean type-C trigger an ACPI event, and this ACPI event can notify
>>> related USB controller driver doing role switch?
>>
>> No (firmware programs the dual-role hw/registers), but never mind.
>> That could be the case.
>>
>>> If it is correct, there is a notifier between type-C and USB
>>> controller driver, how to define this notifier for non-ACPI platform?
>>
>> Once there is a platform with Type-C like that, the problem needs to
>> be solved. However..
>>
>>>> I'm not commenting on Roger's dual role patch series, but I don't
>>>> really think it should be mixed with Type-C. USB Type-C and USB
>>>> Power Delivery define their own ways of handling the roles, and they
>>>> are not limited to the data role only. Things like OTG for example
>>>> will, and actually can not be supported. With Type-C we will have
>>>> competing state machines compared to OTG. The dual-role framework
>>>> may be useful on systems that provide more traditional connectors,
>>>> which possibly have the ID-pin like micro-AB, and possibly also
>>>> support OTG. It can also be something that exist in parallel with the Type-C
>class, but there just can not be any dependencies between the two.
>>>>
>>>
>>> Yes, there are two independent things. But if the kernel doesn't have
>>> a notifier between type-C message sender (type-c class) and message
>>> receiver (like USB controller driver for role switch or other drivers
>>> for alternate mode message), we had to find some ways at userspace.
>>
>> ..what ever the solution is, it really can't rely on user space.
>>
>
>... and, at least for our application, using extcon for the necessary notifications works
>just fine.
>

I see, that means you have a hardware signal to notify role switch.

Peter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-07 22:30               ` Mats Karrman
  2017-03-08  1:38                 ` Guenter Roeck
@ 2017-03-08 13:58                 ` Heikki Krogerus
  2017-03-10 22:22                   ` Mats Karrman
  1 sibling, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-08 13:58 UTC (permalink / raw)
  To: Mats Karrman
  Cc: Guenter Roeck, Greg KH, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb

On Tue, Mar 07, 2017 at 11:30:54PM +0100, Mats Karrman wrote:
> > > So, both the DP controller and the USB PD phy are I2C devices, and now I have to make them both
> > > attach to the AM bus as well?
> > The DP controller would provide the driver and the USB PD phy
> > (actually, the typec class) the device.
> > 
> > Would it be a problem to register these I2C devices with some other
> > subsystem, was it extcon or something like AM bus? It really would not
> > be that uncommon. Or have I misunderstood your question?
> 
> OK, so a bus could be used for drivers to find each other but it still does not say
> anything about how those drivers are supposed to communicate so that must be prescribed
> separately, right?

Yes.

> If I read Heikki's original suggestion I understand it like the DP driver would be
> responsible for AM specific USB PD/VDM communication. But wouldn't that lead
> to a lot of code duplication since the AM protocol is the same for all drivers of
> a kind?

No that's not what I mean. I'm still mixing your PD controller with
something else above, sorry about that. Your PD controller driver
should not ideally even need to be aware of Type-C connector, right?
It definitely does not need to do any USB PD communication.

I would imagine you have on top of the DP controller, a mux (which
could be a DP/USB3 PHY like on Rockchip RK3399, discrete mux like
Pericom PI3USB30532, or something else), and a USB Type-C PHY or USB
PD controller. The bus would be tying the mux to the Type-C port (PHY
or PD controller) and its partner (note that it does not tie the mux
to the DP controller). Please correct me if I'm wrong about your
hardware.

Assuming that is how your board roughly looks like, the driver for the
mux would be the driver for the DP altmode devices. That driver would
be the one converting things like the Attention messages notifying
about HPD into toggling of GPIOs, or what ever is needed on your
board, etc.

The actual PD communication with VDMs should be considered as just the
protocol, so we probable should have "protocol drivers". For example
DP alternate mode VDMs and communication will always be the same
despite of the hardware. The DP alternate mode "protocol driver" would
then be tied to the alternate mode device for the partner, and that
driver could have its own hooks for what ever is needed, like HPD
signal handling, configuration changes, whatever. In any case,
hopefully making things easy and straightforward for the "mux driver",
_so that it does not need to care about the actual PD communication_.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-08  6:50                 ` Peter Chen
@ 2017-03-08 14:44                   ` Guenter Roeck
  2017-03-09  2:00                     ` Peter Chen
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-03-08 14:44 UTC (permalink / raw)
  To: Peter Chen, Heikki Krogerus
  Cc: Peter Chen, Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel,
	linux-usb, Roger Quadros, Jun Li

On 03/07/2017 10:50 PM, Peter Chen wrote:
>
>>>> You mean type-C trigger an ACPI event, and this ACPI event can notify
>>>> related USB controller driver doing role switch?
>>>
>>> No (firmware programs the dual-role hw/registers), but never mind.
>>> That could be the case.
>>>
>>>> If it is correct, there is a notifier between type-C and USB
>>>> controller driver, how to define this notifier for non-ACPI platform?
>>>
>>> Once there is a platform with Type-C like that, the problem needs to
>>> be solved. However..
>>>
>>>>> I'm not commenting on Roger's dual role patch series, but I don't
>>>>> really think it should be mixed with Type-C. USB Type-C and USB
>>>>> Power Delivery define their own ways of handling the roles, and they
>>>>> are not limited to the data role only. Things like OTG for example
>>>>> will, and actually can not be supported. With Type-C we will have
>>>>> competing state machines compared to OTG. The dual-role framework
>>>>> may be useful on systems that provide more traditional connectors,
>>>>> which possibly have the ID-pin like micro-AB, and possibly also
>>>>> support OTG. It can also be something that exist in parallel with the Type-C
>> class, but there just can not be any dependencies between the two.
>>>>>
>>>>
>>>> Yes, there are two independent things. But if the kernel doesn't have
>>>> a notifier between type-C message sender (type-c class) and message
>>>> receiver (like USB controller driver for role switch or other drivers
>>>> for alternate mode message), we had to find some ways at userspace.
>>>
>>> ..what ever the solution is, it really can't rely on user space.
>>>
>>
>> ... and, at least for our application, using extcon for the necessary notifications works
>> just fine.
>>
>
> I see, that means you have a hardware signal to notify role switch.
>

In our case the Type-C protocol manager (including alternate mode handling)
is implemented in an EC. The EC signals the extcon-cros_ec driver, which
in turn signals the phy driver as well as the DP driver. The Type-C class
is orthogonal; extcon-cros_ec will also register with the Type-C class code
once that is upstream.

As mentioned earlier, using extcon for signaling was the most convenient means
for us to pass events around. I am more than open to change it to a bus,
if that can be made to work - we'd have to keep in mind though that this code
already works without Type-C infrastructure and is for the most part already
upstream (the rk3399 code it ties into is upstream, and extcon-cros_ec has been
submitted as https://patchwork.kernel.org/patch/9583045/).

As for to how to handle alternate mode if the Type-C protocol manager
(TCPM) is implemented in the kernel - I have not yet implemented it yet,
but my thinking goes along the line described by Heikki in his last e-mail.

Note that we also have a kernel driver for FUSB302 which ties into my tcpm
driver. I'll have to check if that is public yet and if I or someone
else can publish it if there is interest.

Guenter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-08 14:44                   ` Guenter Roeck
@ 2017-03-09  2:00                     ` Peter Chen
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Chen @ 2017-03-09  2:00 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Peter Chen, Heikki Krogerus, Greg KH, Felipe Balbi,
	Oliver Neukum, linux-kernel, linux-usb, Roger Quadros, Jun Li

On Wed, Mar 08, 2017 at 06:44:47AM -0800, Guenter Roeck wrote:
> On 03/07/2017 10:50 PM, Peter Chen wrote:
> >
> >>>>You mean type-C trigger an ACPI event, and this ACPI event can notify
> >>>>related USB controller driver doing role switch?
> >>>
> >>>No (firmware programs the dual-role hw/registers), but never mind.
> >>>That could be the case.
> >>>
> >>>>If it is correct, there is a notifier between type-C and USB
> >>>>controller driver, how to define this notifier for non-ACPI platform?
> >>>
> >>>Once there is a platform with Type-C like that, the problem needs to
> >>>be solved. However..
> >>>
> >>>>>I'm not commenting on Roger's dual role patch series, but I don't
> >>>>>really think it should be mixed with Type-C. USB Type-C and USB
> >>>>>Power Delivery define their own ways of handling the roles, and they
> >>>>>are not limited to the data role only. Things like OTG for example
> >>>>>will, and actually can not be supported. With Type-C we will have
> >>>>>competing state machines compared to OTG. The dual-role framework
> >>>>>may be useful on systems that provide more traditional connectors,
> >>>>>which possibly have the ID-pin like micro-AB, and possibly also
> >>>>>support OTG. It can also be something that exist in parallel with the Type-C
> >>class, but there just can not be any dependencies between the two.
> >>>>>
> >>>>
> >>>>Yes, there are two independent things. But if the kernel doesn't have
> >>>>a notifier between type-C message sender (type-c class) and message
> >>>>receiver (like USB controller driver for role switch or other drivers
> >>>>for alternate mode message), we had to find some ways at userspace.
> >>>
> >>>..what ever the solution is, it really can't rely on user space.
> >>>
> >>
> >>... and, at least for our application, using extcon for the necessary notifications works
> >>just fine.
> >>
> >
> >I see, that means you have a hardware signal to notify role switch.
> >
> 
> In our case the Type-C protocol manager (including alternate mode handling)
> is implemented in an EC. The EC signals the extcon-cros_ec driver, which
> in turn signals the phy driver as well as the DP driver. The Type-C class
> is orthogonal; extcon-cros_ec will also register with the Type-C class code
> once that is upstream.
> 
> As mentioned earlier, using extcon for signaling was the most convenient means
> for us to pass events around. I am more than open to change it to a bus,
> if that can be made to work - we'd have to keep in mind though that this code
> already works without Type-C infrastructure and is for the most part already
> upstream (the rk3399 code it ties into is upstream, and extcon-cros_ec has been
> submitted as https://patchwork.kernel.org/patch/9583045/).
> 

I am clear your implementation now, thank, Guenter.

> As for to how to handle alternate mode if the Type-C protocol manager
> (TCPM) is implemented in the kernel - I have not yet implemented it yet,
> but my thinking goes along the line described by Heikki in his last e-mail.
> 
> Note that we also have a kernel driver for FUSB302 which ties into my tcpm
> driver. I'll have to check if that is public yet and if I or someone
> else can publish it if there is interest.
> 
> Guenter
> 

-- 

Best Regards,
Peter Chen

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-08 13:58                 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
@ 2017-03-10 22:22                   ` Mats Karrman
  2017-03-10 23:41                     ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Mats Karrman @ 2017-03-10 22:22 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Greg KH, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb

On 2017-03-08 14:58, Heikki Krogerus wrote:

> On Tue, Mar 07, 2017 at 11:30:54PM +0100, Mats Karrman wrote:
>> If I read Heikki's original suggestion I understand it like the DP driver would be
>> responsible for AM specific USB PD/VDM communication. But wouldn't that lead
>> to a lot of code duplication since the AM protocol is the same for all drivers of
>> a kind?
> No that's not what I mean. I'm still mixing your PD controller with
> something else above, sorry about that. Your PD controller driver
> should not ideally even need to be aware of Type-C connector, right?
> It definitely does not need to do any USB PD communication.

Right.

> I would imagine you have on top of the DP controller, a mux (which
> could be a DP/USB3 PHY like on Rockchip RK3399, discrete mux like
> Pericom PI3USB30532, or something else), and a USB Type-C PHY or USB
> PD controller. The bus would be tying the mux to the Type-C port (PHY
> or PD controller) and its partner (note that it does not tie the mux
> to the DP controller). Please correct me if I'm wrong about your
> hardware.

No, you're correct, a discrete mux and a fusb302.

> Assuming that is how your board roughly looks like, the driver for the
> mux would be the driver for the DP altmode devices. That driver would
> be the one converting things like the Attention messages notifying
> about HPD into toggling of GPIOs, or what ever is needed on your
> board, etc.

OK.

> The actual PD communication with VDMs should be considered as just the
> protocol, so we probable should have "protocol drivers". For example
> DP alternate mode VDMs and communication will always be the same
> despite of the hardware. The DP alternate mode "protocol driver" would
> then be tied to the alternate mode device for the partner, and that
> driver could have its own hooks for what ever is needed, like HPD
> signal handling, configuration changes, whatever. In any case,
> hopefully making things easy and straightforward for the "mux driver",
> _so that it does not need to care about the actual PD communication_.

I'm digesting your and Guenter's replies and patches.
I will try getting something up and running too soon and hopefully the foggy parts will
dissolve. As for now I find it a lot easier to grok Guenter's drivers than to see the
advantages and/or disadvantages of an altmode bus :-)

@Guenter: There _is_ interest for your fusb302 driver, thank you

BR // Mats

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-10 22:22                   ` Mats Karrman
@ 2017-03-10 23:41                     ` Guenter Roeck
  2017-04-18 18:52                       ` Badhri Jagan Sridharan
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-03-10 23:41 UTC (permalink / raw)
  To: Mats Karrman, Heikki Krogerus
  Cc: Greg KH, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 03/10/2017 02:22 PM, Mats Karrman wrote:
> On 2017-03-08 14:58, Heikki Krogerus wrote:
>
>> On Tue, Mar 07, 2017 at 11:30:54PM +0100, Mats Karrman wrote:
>>> If I read Heikki's original suggestion I understand it like the DP driver would be
>>> responsible for AM specific USB PD/VDM communication. But wouldn't that lead
>>> to a lot of code duplication since the AM protocol is the same for all drivers of
>>> a kind?
>> No that's not what I mean. I'm still mixing your PD controller with
>> something else above, sorry about that. Your PD controller driver
>> should not ideally even need to be aware of Type-C connector, right?
>> It definitely does not need to do any USB PD communication.
>
> Right.
>
>> I would imagine you have on top of the DP controller, a mux (which
>> could be a DP/USB3 PHY like on Rockchip RK3399, discrete mux like
>> Pericom PI3USB30532, or something else), and a USB Type-C PHY or USB
>> PD controller. The bus would be tying the mux to the Type-C port (PHY
>> or PD controller) and its partner (note that it does not tie the mux
>> to the DP controller). Please correct me if I'm wrong about your
>> hardware.
>
> No, you're correct, a discrete mux and a fusb302.
>
>> Assuming that is how your board roughly looks like, the driver for the
>> mux would be the driver for the DP altmode devices. That driver would
>> be the one converting things like the Attention messages notifying
>> about HPD into toggling of GPIOs, or what ever is needed on your
>> board, etc.
>
> OK.
>
>> The actual PD communication with VDMs should be considered as just the
>> protocol, so we probable should have "protocol drivers". For example
>> DP alternate mode VDMs and communication will always be the same
>> despite of the hardware. The DP alternate mode "protocol driver" would
>> then be tied to the alternate mode device for the partner, and that
>> driver could have its own hooks for what ever is needed, like HPD
>> signal handling, configuration changes, whatever. In any case,
>> hopefully making things easy and straightforward for the "mux driver",
>> _so that it does not need to care about the actual PD communication_.
>
> I'm digesting your and Guenter's replies and patches.
> I will try getting something up and running too soon and hopefully the foggy parts will
> dissolve. As for now I find it a lot easier to grok Guenter's drivers than to see the
> advantages and/or disadvantages of an altmode bus :-)
>
> @Guenter: There _is_ interest for your fusb302 driver, thank you
>

Ok, I'll see what I need to do to publish it.

Guenter

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

* Re: [PATCH v17 0/3] USB Type-C Connector class
  2017-02-21 14:24 [PATCH v17 0/3] USB Type-C Connector class Heikki Krogerus
                   ` (3 preceding siblings ...)
  2017-02-21 15:42 ` [PATCH v17 0/3] USB Type-C Connector class Felipe Balbi
@ 2017-03-21 10:23 ` Greg KH
  2017-03-21 10:37   ` Heikki Krogerus
  4 siblings, 1 reply; 64+ messages in thread
From: Greg KH @ 2017-03-21 10:23 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On Tue, Feb 21, 2017 at 05:24:02PM +0300, Heikki Krogerus wrote:
> The USB Type-C class is meant to provide unified interface to the
> userspace to present the USB Type-C ports in a system.
> 
> Changes since v16:
> - Using PTR_ERR_OR_ZERO macro in typec_init().

I'm lost in the long thread here, is this series still ready to be
merged in, or is there another version that is being worked on?

thanks,

greg k-h

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

* Re: [PATCH v17 0/3] USB Type-C Connector class
  2017-03-21 10:23 ` Greg KH
@ 2017-03-21 10:37   ` Heikki Krogerus
  2017-03-22 21:15     ` Mats Karrman
  0 siblings, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-21 10:37 UTC (permalink / raw)
  To: Greg KH
  Cc: Guenter Roeck, Mats Karrman, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb

On Tue, Mar 21, 2017 at 11:23:37AM +0100, Greg KH wrote:
> On Tue, Feb 21, 2017 at 05:24:02PM +0300, Heikki Krogerus wrote:
> > The USB Type-C class is meant to provide unified interface to the
> > userspace to present the USB Type-C ports in a system.
> > 
> > Changes since v16:
> > - Using PTR_ERR_OR_ZERO macro in typec_init().
> 
> I'm lost in the long thread here, is this series still ready to be
> merged in, or is there another version that is being worked on?

There was one documentation fix proposed Mats. The rest of the thread
was not about these patches.

I'll send one more version and fix the documentation.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 0/3] USB Type-C Connector class
  2017-02-21 15:42 ` [PATCH v17 0/3] USB Type-C Connector class Felipe Balbi
@ 2017-03-21 11:14   ` Heikki Krogerus
  0 siblings, 0 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-21 11:14 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: Greg KH, Guenter Roeck, Oliver Neukum, linux-kernel, linux-usb

On Tue, Feb 21, 2017 at 05:42:35PM +0200, Felipe Balbi wrote:
> Just to clarify one thing here: wherever it says "Reviewed-by: Felipe
> Balbi..." you could also read "Reviewed-and-Tested-by: Felipe Balbi..."
> as I have been running these patches for past few months to test code on
> Intel Joule.

OK :-)


Thanks,

-- 
heikki

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

* Re: [PATCH v17 0/3] USB Type-C Connector class
  2017-03-21 10:37   ` Heikki Krogerus
@ 2017-03-22 21:15     ` Mats Karrman
  2017-03-23  8:16       ` Heikki Krogerus
  0 siblings, 1 reply; 64+ messages in thread
From: Mats Karrman @ 2017-03-22 21:15 UTC (permalink / raw)
  To: Heikki Krogerus, Greg KH
  Cc: Guenter Roeck, Felipe Balbi, Oliver Neukum, linux-kernel, linux-usb

On 03/21/2017 11:37 AM, Heikki Krogerus wrote:

>> I'm lost in the long thread here, is this series still ready to be
>> merged in, or is there another version that is being worked on?
> There was one documentation fix proposed Mats. The rest of the thread
> was not about these patches.
>
> I'll send one more version and fix the documentation.
>
A bit late but...

After reading a bit more I found that there is a miss-match between
Documentation/ABI/testing/sysfs-class-typec on one side and the actual
code and Documentation/usb/typec.rst on the other side. In the first it
looks like all attribute groups are flat under typec/ but in the code
and the other document they are instead created in a tree, e.g.:

/sys/class/typec/port0/
/sys/class/typec/port0/svid-ff01/
/sys/class/typec/port0/svid-ff01/mode0/
/sys/class/typec/port0/port0-partner/
/sys/class/typec/port0/port0-cable/
/sys/class/typec/port0/port0-cable/identity/
/sys/class/typec/port0/port0-cable/port0-plug0/
/sys/class/typec/port0/port0-cable/port0-plug1/

BR // Mats

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

* Re: [PATCH v17 0/3] USB Type-C Connector class
  2017-03-22 21:15     ` Mats Karrman
@ 2017-03-23  8:16       ` Heikki Krogerus
  0 siblings, 0 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-03-23  8:16 UTC (permalink / raw)
  To: Mats Karrman
  Cc: Greg KH, Guenter Roeck, Felipe Balbi, Oliver Neukum,
	linux-kernel, linux-usb

Hi Mats,

On Wed, Mar 22, 2017 at 10:15:20PM +0100, Mats Karrman wrote:
> On 03/21/2017 11:37 AM, Heikki Krogerus wrote:
> 
> > > I'm lost in the long thread here, is this series still ready to be
> > > merged in, or is there another version that is being worked on?
> > There was one documentation fix proposed Mats. The rest of the thread
> > was not about these patches.
> > 
> > I'll send one more version and fix the documentation.
> > 
> A bit late but...
> 
> After reading a bit more I found that there is a miss-match between
> Documentation/ABI/testing/sysfs-class-typec on one side and the actual
> code and Documentation/usb/typec.rst on the other side. In the first it
> looks like all attribute groups are flat under typec/ but in the code
> and the other document they are instead created in a tree, e.g.:
> 
> /sys/class/typec/port0/
> /sys/class/typec/port0/svid-ff01/
> /sys/class/typec/port0/svid-ff01/mode0/
> /sys/class/typec/port0/port0-partner/
> /sys/class/typec/port0/port0-cable/
> /sys/class/typec/port0/port0-cable/identity/
> /sys/class/typec/port0/port0-cable/port0-plug0/
> /sys/class/typec/port0/port0-cable/port0-plug1/

Documentation/ABI/testing/sysfs-class-typec describes the attributes
from the classes point of view.

Documentation/usb/typec.rst tries to explain the actual hierarchy of
the devices that the current typec class driver generates, however the
"class" does not care about that. Every device will simply have a link
added to the class directory (/sys/class/typec/ in our case)
regardless of their parent. For example, port0 and its partners:

/sys/class/typec/port0		-> ../../devices/<path>/<to>/<your>/<device>/typec/port0
/sys/class/typec/port0-partner	-> ../../devices/<path>/<to>/<your>/<device>/typec/port0/port0-partner
/sys/class/typec/port0-cable	-> ../../devices/<path>/<to>/<your>/<device>/typec/port0/port0-cable
/sys/class/typec/port0-plug0	-> ../../devices/<path>/<to>/<your>/<device>/typec/port0/port0-cable/port0-plug0
/sys/class/typec/port0-plug1	-> ../../devices/<path>/<to>/<your>/<device>/typec/port0/port0-cable/port0-plug1


Thanks,

-- 
heikki

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

* USB Type-C Port Manager API concern
  2017-03-08  1:38                 ` Guenter Roeck
@ 2017-04-08 23:09                   ` Mats Karrman
  2017-04-09 15:16                     ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Mats Karrman @ 2017-04-08 23:09 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, linux-kernel, linux-usb

Hi Guenter,

 From a previous thread:

On 03/08/2017 02:38 AM, Guenter Roeck wrote:
> On 03/07/2017 02:30 PM, Mats Karrman wrote:
> [ ... ]
>
>>
>> I'm still struggling to catch up on what you guys have been up to 
>> during the
>> last year or so :-) and came across some patches of Guenter from last 
>> October:
>>
>> http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1243527.html
>>
>> What happened to them? Has there been any progress since then?
>>
>
> Updates to keep in sync with API changes, bug fixes, and minor 
> improvements,
> for the most part. I can post a current version if there is interest.
> The latest version is also available from
> https://chromium-review.googlesource.com/#/c/389917/

I'm working on a tcpi driver and have some concern about the tcpm api.
The tcpm_register_port() is typically called from the probe function of
tcpi driver where the tcpm_port reference returned is stored in the
driver private data. The problem I ran into is that tcpm_register_port()
calls back to the not yet fully initialized tcpi driver, causing null-
pointer dereferences. This could of course be solved by extra logic in
the tcpi driver but I think it would be more elegant if the registration
of a port could be free of premature callbacks. E.g. it could be required
that the tcpi driver probe called tcpm_tcpc_reset() once it's done
initializing or the necessary data could be supplied in the call to
tcpm_register_port().
What do you think?

BR,
Mats

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

* Re: USB Type-C Port Manager API concern
  2017-04-08 23:09                   ` USB Type-C Port Manager API concern Mats Karrman
@ 2017-04-09 15:16                     ` Guenter Roeck
  2017-04-09 21:05                       ` Mats Karrman
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-04-09 15:16 UTC (permalink / raw)
  To: Mats Karrman
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, linux-kernel, linux-usb

Hi Mats,

On Sun, Apr 09, 2017 at 01:09:57AM +0200, Mats Karrman wrote:
> Hi Guenter,
> 
> From a previous thread:
> 
> On 03/08/2017 02:38 AM, Guenter Roeck wrote:
> >On 03/07/2017 02:30 PM, Mats Karrman wrote:
> >[ ... ]
> >
> >>
> >>I'm still struggling to catch up on what you guys have been up to during
> >>the
> >>last year or so :-) and came across some patches of Guenter from last
> >>October:
> >>
> >>http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1243527.html
> >>
> >>What happened to them? Has there been any progress since then?
> >>
> >
> >Updates to keep in sync with API changes, bug fixes, and minor
> >improvements,
> >for the most part. I can post a current version if there is interest.
> >The latest version is also available from
> >https://chromium-review.googlesource.com/#/c/389917/
> 
> I'm working on a tcpi driver and have some concern about the tcpm api.
> The tcpm_register_port() is typically called from the probe function of
> tcpi driver where the tcpm_port reference returned is stored in the
> driver private data. The problem I ran into is that tcpm_register_port()
> calls back to the not yet fully initialized tcpi driver, causing null-
> pointer dereferences. This could of course be solved by extra logic in
> the tcpi driver but I think it would be more elegant if the registration
> of a port could be free of premature callbacks. E.g. it could be required
> that the tcpi driver probe called tcpm_tcpc_reset() once it's done
> initializing or the necessary data could be supplied in the call to
> tcpm_register_port().
> What do you think?

Let me think about it. In theory it should be possible to avoid callbacks into
the underlying driver until after the return from the registration code, but
that would still be racy if the underlying driver is not ready.

Basic problem seems to be that an API in general assumes that the caller is
ready to serve it once it registers itself. It is kind of unusual to have two
calls, one to register the driver and one to tell the infrastructure that it
is ready (which I assume your reset call would do). Ultimately this means
that the tcpm driver would have to have additional logic to identify if the
underlying driver is ready to handle callbacks.

Can you delay tcpm registration until after the underlying driver is ready,
ie typically to the end of its probe function ? Or am I misunderstanding
your problem ?

Thanks,
Guenter

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

* Re: USB Type-C Port Manager API concern
  2017-04-09 15:16                     ` Guenter Roeck
@ 2017-04-09 21:05                       ` Mats Karrman
  2017-04-14  2:57                         ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Mats Karrman @ 2017-04-09 21:05 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, linux-kernel, linux-usb

On 04/09/2017 05:16 PM, Guenter Roeck wrote:

> Hi Mats,
>
> On Sun, Apr 09, 2017 at 01:09:57AM +0200, Mats Karrman wrote:
>> I'm working on a tcpi driver and have some concern about the tcpm api.
>> The tcpm_register_port() is typically called from the probe function of
>> tcpi driver where the tcpm_port reference returned is stored in the
>> driver private data. The problem I ran into is that tcpm_register_port()
>> calls back to the not yet fully initialized tcpi driver, causing null-
>> pointer dereferences. This could of course be solved by extra logic in
>> the tcpi driver but I think it would be more elegant if the registration
>> of a port could be free of premature callbacks. E.g. it could be required
>> that the tcpi driver probe called tcpm_tcpc_reset() once it's done
>> initializing or the necessary data could be supplied in the call to
>> tcpm_register_port().
>> What do you think?
> Let me think about it. In theory it should be possible to avoid callbacks into
> the underlying driver until after the return from the registration code, but
> that would still be racy if the underlying driver is not ready.
>
> Basic problem seems to be that an API in general assumes that the caller is
> ready to serve it once it registers itself. It is kind of unusual to have two
> calls, one to register the driver and one to tell the infrastructure that it
> is ready (which I assume your reset call would do). Ultimately this means
> that the tcpm driver would have to have additional logic to identify if the
> underlying driver is ready to handle callbacks.
>
> Can you delay tcpm registration until after the underlying driver is ready,
> ie typically to the end of its probe function ? Or am I misunderstanding
> your problem ?

The problem I had was that I was trying to pull the same trick that you do ;)
I.e. the probe function calls tcpm_register_port() that is calling back
to the driver that was trying to call back to tcpm, just that the call to
tcpm_register_port() has not yet returned so the pointer to tcpm_port in the
driver data structure was still null.

I was able to fix the issue by commenting out the call to tcpm_init() at the
end of tcpm_register_port() and instead call ("your") tcpm_tcpc_reset(), that
currently does nothing but calling tcpm_init(), after I'm done.

Even though I'm not overly excited about the tcpm register function calling back
to the driver I don't think my fix is much better. I should live by my own words
and refrain from calling back to tcpm until registration has finished...

// Mats

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

* Re: USB Type-C Port Manager API concern
  2017-04-09 21:05                       ` Mats Karrman
@ 2017-04-14  2:57                         ` Guenter Roeck
  2017-04-14  8:30                           ` Mats Karrman
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-04-14  2:57 UTC (permalink / raw)
  To: Mats Karrman
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, linux-kernel, linux-usb

On 04/09/2017 02:05 PM, Mats Karrman wrote:
> On 04/09/2017 05:16 PM, Guenter Roeck wrote:
>
>> Hi Mats,
>>
>> On Sun, Apr 09, 2017 at 01:09:57AM +0200, Mats Karrman wrote:
>>> I'm working on a tcpi driver and have some concern about the tcpm api.
>>> The tcpm_register_port() is typically called from the probe function of
>>> tcpi driver where the tcpm_port reference returned is stored in the
>>> driver private data. The problem I ran into is that tcpm_register_port()
>>> calls back to the not yet fully initialized tcpi driver, causing null-
>>> pointer dereferences. This could of course be solved by extra logic in
>>> the tcpi driver but I think it would be more elegant if the registration
>>> of a port could be free of premature callbacks. E.g. it could be required
>>> that the tcpi driver probe called tcpm_tcpc_reset() once it's done
>>> initializing or the necessary data could be supplied in the call to
>>> tcpm_register_port().
>>> What do you think?
>> Let me think about it. In theory it should be possible to avoid callbacks into
>> the underlying driver until after the return from the registration code, but
>> that would still be racy if the underlying driver is not ready.
>>
>> Basic problem seems to be that an API in general assumes that the caller is
>> ready to serve it once it registers itself. It is kind of unusual to have two
>> calls, one to register the driver and one to tell the infrastructure that it
>> is ready (which I assume your reset call would do). Ultimately this means
>> that the tcpm driver would have to have additional logic to identify if the
>> underlying driver is ready to handle callbacks.
>>
>> Can you delay tcpm registration until after the underlying driver is ready,
>> ie typically to the end of its probe function ? Or am I misunderstanding
>> your problem ?
>
> The problem I had was that I was trying to pull the same trick that you do ;)
> I.e. the probe function calls tcpm_register_port() that is calling back
> to the driver that was trying to call back to tcpm, just that the call to
> tcpm_register_port() has not yet returned so the pointer to tcpm_port in the
> driver data structure was still null.
>
> I was able to fix the issue by commenting out the call to tcpm_init() at the
> end of tcpm_register_port() and instead call ("your") tcpm_tcpc_reset(), that
> currently does nothing but calling tcpm_init(), after I'm done.
>
> Even though I'm not overly excited about the tcpm register function calling back
> to the driver I don't think my fix is much better. I should live by my own words
> and refrain from calling back to tcpm until registration has finished...
>
Problem is that I can't even defer the call to tcpm_init(), or for that matter any
other call into the low level driver code, into the worker, since there is still
no guarantee that the low level driver is "done" with its initialization. The only
real solution I can think of is that the low level driver should not use the pointer
to tcpm_port in any of its callback functions.

Overall I think there is an assumption in any API that any callback functions provided
in a registration call can immediately be called. Otherwise any API would be in trouble.
Can you modify your code to not require the port pointer in its callback functions ?

Thanks,
Guenter

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

* Re: USB Type-C Port Manager API concern
  2017-04-14  2:57                         ` Guenter Roeck
@ 2017-04-14  8:30                           ` Mats Karrman
  0 siblings, 0 replies; 64+ messages in thread
From: Mats Karrman @ 2017-04-14  8:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Greg KH, Felipe Balbi, linux-kernel, linux-usb

On 04/14/2017 04:57 AM, Guenter Roeck wrote:

> ... Overall I think there is an assumption in any API that any 
> callback functions provided in a registration call can immediately be 
> called. Otherwise any API would be in trouble. Can you modify your 
> code to not require the port pointer in its callback functions ?

Yes, I have deferred my calls until after the registration function has 
returned which seems only logical. Thanks, Mats

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-03-10 23:41                     ` Guenter Roeck
@ 2017-04-18 18:52                       ` Badhri Jagan Sridharan
  2017-04-19 11:23                         ` Heikki Krogerus
  0 siblings, 1 reply; 64+ messages in thread
From: Badhri Jagan Sridharan @ 2017-04-18 18:52 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Mats Karrman, Heikki Krogerus, Greg KH, Felipe Balbi,
	Oliver Neukum, LKML, USB

Hi Heikki,

I have a question regarding the preferred_role node.

+What:          /sys/class/typec/<port>/preferred_role
+Date:          March 2017
+Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+               The user space can notify the driver about the preferred role.
+               It should be handled as enabling of Try.SRC or Try.SNK, as
+               defined in USB Type-C specification, in the port drivers. By
+               default the preferred role should come from the platform.
+
+               Valid values: source, sink, none (to remove preference)

What is the expected behavior when the userspace changes the
preferred_role node when the port is in connected state ?

1.  the state machine re-resolves the port roles right away based on
the new state machine in place ? (or)
2. Wait till the subsequent connect for resolving port roles based on the
new state machine.

For #1 to happen the policy_engine layer would have to reset the port
to resolve the port roles based on the (Try.SRC /Try.SNK/ Default)
new state machine preference.

Say for example when two non-PD devices following none (default state
machine) are connected, the port role resolution is going to be random.
But, if the userspace in one of the devices later changes the
preferred_role to source, then that device is most likely to become source
if the Try.SRC state-machine is re-run.

Does the above question fall under a policy decision ? If so, should there
be another node to say if the port roles have to re-resolved  based on the
new state machine right away ?

Thanks !!

On Fri, Mar 10, 2017 at 3:41 PM, Guenter Roeck <linux@roeck-us.net> wrote:
> On 03/10/2017 02:22 PM, Mats Karrman wrote:
>>
>> On 2017-03-08 14:58, Heikki Krogerus wrote:
>>
>>> On Tue, Mar 07, 2017 at 11:30:54PM +0100, Mats Karrman wrote:
>>>>
>>>> If I read Heikki's original suggestion I understand it like the DP
>>>> driver would be
>>>> responsible for AM specific USB PD/VDM communication. But wouldn't that
>>>> lead
>>>> to a lot of code duplication since the AM protocol is the same for all
>>>> drivers of
>>>> a kind?
>>>
>>> No that's not what I mean. I'm still mixing your PD controller with
>>> something else above, sorry about that. Your PD controller driver
>>> should not ideally even need to be aware of Type-C connector, right?
>>> It definitely does not need to do any USB PD communication.
>>
>>
>> Right.
>>
>>> I would imagine you have on top of the DP controller, a mux (which
>>> could be a DP/USB3 PHY like on Rockchip RK3399, discrete mux like
>>> Pericom PI3USB30532, or something else), and a USB Type-C PHY or USB
>>> PD controller. The bus would be tying the mux to the Type-C port (PHY
>>> or PD controller) and its partner (note that it does not tie the mux
>>> to the DP controller). Please correct me if I'm wrong about your
>>> hardware.
>>
>>
>> No, you're correct, a discrete mux and a fusb302.
>>
>>> Assuming that is how your board roughly looks like, the driver for the
>>> mux would be the driver for the DP altmode devices. That driver would
>>> be the one converting things like the Attention messages notifying
>>> about HPD into toggling of GPIOs, or what ever is needed on your
>>> board, etc.
>>
>>
>> OK.
>>
>>> The actual PD communication with VDMs should be considered as just the
>>> protocol, so we probable should have "protocol drivers". For example
>>> DP alternate mode VDMs and communication will always be the same
>>> despite of the hardware. The DP alternate mode "protocol driver" would
>>> then be tied to the alternate mode device for the partner, and that
>>> driver could have its own hooks for what ever is needed, like HPD
>>> signal handling, configuration changes, whatever. In any case,
>>> hopefully making things easy and straightforward for the "mux driver",
>>> _so that it does not need to care about the actual PD communication_.
>>
>>
>> I'm digesting your and Guenter's replies and patches.
>> I will try getting something up and running too soon and hopefully the
>> foggy parts will
>> dissolve. As for now I find it a lot easier to grok Guenter's drivers than
>> to see the
>> advantages and/or disadvantages of an altmode bus :-)
>>
>> @Guenter: There _is_ interest for your fusb302 driver, thank you
>>
>
> Ok, I'll see what I need to do to publish it.
>
> Guenter
>
>
> --
> 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] 64+ messages in thread

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-18 18:52                       ` Badhri Jagan Sridharan
@ 2017-04-19 11:23                         ` Heikki Krogerus
  2017-04-19 14:45                           ` Badhri Jagan Sridharan
  0 siblings, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-04-19 11:23 UTC (permalink / raw)
  To: Badhri Jagan Sridharan, Oliver Neukum
  Cc: Guenter Roeck, Mats Karrman, Greg KH, Felipe Balbi, LKML, USB

Hi,

On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
> Hi Heikki,
> 
> I have a question regarding the preferred_role node.
> 
> +What:          /sys/class/typec/<port>/preferred_role
> +Date:          March 2017
> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
> +Description:
> +               The user space can notify the driver about the preferred role.
> +               It should be handled as enabling of Try.SRC or Try.SNK, as
> +               defined in USB Type-C specification, in the port drivers. By
> +               default the preferred role should come from the platform.
> +
> +               Valid values: source, sink, none (to remove preference)
> 
> What is the expected behavior when the userspace changes the
> preferred_role node when the port is in connected state ?
> 
> 1.  the state machine re-resolves the port roles right away based on
> the new state machine in place ? (or)

No! There are separate attributes for sending role swap requests.

The attribute will "enable" Try.SRC/SNK states, i.e. next time the
state machine is executed, those states need to be considered.
Changing the value of this attribute must not affect the current
connection.

> 2. Wait till the subsequent connect for resolving port roles based on the
> new state machine.

Yes.

> For #1 to happen the policy_engine layer would have to reset the port
> to resolve the port roles based on the (Try.SRC /Try.SNK/ Default)
> new state machine preference.
> 
> Say for example when two non-PD devices following none (default state
> machine) are connected, the port role resolution is going to be random.
> But, if the userspace in one of the devices later changes the
> preferred_role to source, then that device is most likely to become source
> if the Try.SRC state-machine is re-run.
> 
> Does the above question fall under a policy decision ? If so, should there
> be another node to say if the port roles have to re-resolved  based on the
> new state machine right away ?

I don't think we should even consider option #1, but just to be sure,
Oliver, what do you say?

I guess we need to say in the documentation explicitly that changing
the value will not affect the current connection.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-19 11:23                         ` Heikki Krogerus
@ 2017-04-19 14:45                           ` Badhri Jagan Sridharan
  2017-04-19 15:14                             ` Guenter Roeck
  2017-04-20 11:55                             ` Heikki Krogerus
  0 siblings, 2 replies; 64+ messages in thread
From: Badhri Jagan Sridharan @ 2017-04-19 14:45 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Oliver Neukum, Guenter Roeck, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
> Hi,
>
> On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
>> Hi Heikki,
>>
>> I have a question regarding the preferred_role node.
>>
>> +What:          /sys/class/typec/<port>/preferred_role
>> +Date:          March 2017
>> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> +Description:
>> +               The user space can notify the driver about the preferred role.
>> +               It should be handled as enabling of Try.SRC or Try.SNK, as
>> +               defined in USB Type-C specification, in the port drivers. By
>> +               default the preferred role should come from the platform.
>> +
>> +               Valid values: source, sink, none (to remove preference)
>>
>> What is the expected behavior when the userspace changes the
>> preferred_role node when the port is in connected state ?
>>
>> 1.  the state machine re-resolves the port roles right away based on
>> the new state machine in place ? (or)
>
> No! There are separate attributes for sending role swap requests.

Right. But, that might not be helpful in cases when PD is not implemented.
and Implementing PD is not mandatory according the spec :/

FYI quoting from the Type-C specification release(page 24),
role swaps are not limited to devices that only support PD.

"Two independent set of mechanisms are defined to allow a USB Type-C
DRP to functionally swap power and data roles. When USB PD is
supported, power and data role swapping is performed as a subsequent
step following the initial connection process. For non-PD implementations,
power/data role swapping can optionally be dealt with as part of the initial
connection process."

But, the current interface definition actually prevents current/data role
swaps for non-pd devices.

>
> The attribute will "enable" Try.SRC/SNK states, i.e. next time the
> state machine is executed, those states need to be considered.
> Changing the value of this attribute must not affect the current
> connection.
>
>> 2. Wait till the subsequent connect for resolving port roles based on the
>> new state machine.
>
> Yes.
>
>> For #1 to happen the policy_engine layer would have to reset the port
>> to resolve the port roles based on the (Try.SRC /Try.SNK/ Default)
>> new state machine preference.
>>
>> Say for example when two non-PD devices following none (default state
>> machine) are connected, the port role resolution is going to be random.
>> But, if the userspace in one of the devices later changes the
>> preferred_role to source, then that device is most likely to become source
>> if the Try.SRC state-machine is re-run.
>>
>> Does the above question fall under a policy decision ? If so, should there
>> be another node to say if the port roles have to re-resolved  based on the
>> new state machine right away ?
>
> I don't think we should even consider option #1, but just to be sure,
> Oliver, what do you say?

Can we at least consider exposing a port_reset field so that the userspace
at least has an option to make the state machine to kick in right away with
a hard reset ?

Please do consider. We can't expect all low-end phones and devices with
smaller form factors then phones to implement PD as it might be an overkill
for them.

>
> I guess we need to say in the documentation explicitly that changing
> the value will not affect the current connection.
>
>
> Thanks,
>
> --
> heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-19 14:45                           ` Badhri Jagan Sridharan
@ 2017-04-19 15:14                             ` Guenter Roeck
  2017-04-19 17:22                               ` Badhri Jagan Sridharan
  2017-04-20 11:55                             ` Heikki Krogerus
  1 sibling, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-04-19 15:14 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Heikki Krogerus, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
> <heikki.krogerus@linux.intel.com> wrote:
> > Hi,
> >
> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
> >> Hi Heikki,
> >>
> >> I have a question regarding the preferred_role node.
> >>
> >> +What:          /sys/class/typec/<port>/preferred_role
> >> +Date:          March 2017
> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
> >> +Description:
> >> +               The user space can notify the driver about the preferred role.
> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
> >> +               defined in USB Type-C specification, in the port drivers. By
> >> +               default the preferred role should come from the platform.
> >> +
> >> +               Valid values: source, sink, none (to remove preference)
> >>
> >> What is the expected behavior when the userspace changes the
> >> preferred_role node when the port is in connected state ?
> >>
> >> 1.  the state machine re-resolves the port roles right away based on
> >> the new state machine in place ? (or)
> >
> > No! There are separate attributes for sending role swap requests.
> 
> Right. But, that might not be helpful in cases when PD is not implemented.
> and Implementing PD is not mandatory according the spec :/
> 
> FYI quoting from the Type-C specification release(page 24),
> role swaps are not limited to devices that only support PD.
> 
> "Two independent set of mechanisms are defined to allow a USB Type-C
> DRP to functionally swap power and data roles. When USB PD is
> supported, power and data role swapping is performed as a subsequent
> step following the initial connection process. For non-PD implementations,
> power/data role swapping can optionally be dealt with as part of the initial
> connection process."
> 
> But, the current interface definition actually prevents current/data role
> swaps for non-pd devices.
> 
This is correct for the attribute definition, but it is not implemented
that way. Writing the attribute is only read-only for non-DRP ports.
Given the standard, I would consider that to be intentional; it might
make sense to update the description accordingly.

How about implementing a mechanism in the dr_set and pr_set code in tcpm
which would handle that situation ? Something along the line of

	if (!port->pd_capable && connected && current role != desired role) {
		reset_port();
		goto done;
	}

My current code doesn't handle the !pd_capable state, so I'll need to do
something anyway.

Thanks,
Guenter

> >
> > The attribute will "enable" Try.SRC/SNK states, i.e. next time the
> > state machine is executed, those states need to be considered.
> > Changing the value of this attribute must not affect the current
> > connection.
> >
> >> 2. Wait till the subsequent connect for resolving port roles based on the
> >> new state machine.
> >
> > Yes.
> >
> >> For #1 to happen the policy_engine layer would have to reset the port
> >> to resolve the port roles based on the (Try.SRC /Try.SNK/ Default)
> >> new state machine preference.
> >>
> >> Say for example when two non-PD devices following none (default state
> >> machine) are connected, the port role resolution is going to be random.
> >> But, if the userspace in one of the devices later changes the
> >> preferred_role to source, then that device is most likely to become source
> >> if the Try.SRC state-machine is re-run.
> >>
> >> Does the above question fall under a policy decision ? If so, should there
> >> be another node to say if the port roles have to re-resolved  based on the
> >> new state machine right away ?
> >
> > I don't think we should even consider option #1, but just to be sure,
> > Oliver, what do you say?
> 
> Can we at least consider exposing a port_reset field so that the userspace
> at least has an option to make the state machine to kick in right away with
> a hard reset ?
> 
> Please do consider. We can't expect all low-end phones and devices with
> smaller form factors then phones to implement PD as it might be an overkill
> for them.
> 
> >
> > I guess we need to say in the documentation explicitly that changing
> > the value will not affect the current connection.
> >
> >
> > Thanks,
> >
> > --
> > heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-19 15:14                             ` Guenter Roeck
@ 2017-04-19 17:22                               ` Badhri Jagan Sridharan
  2017-04-19 19:29                                 ` Guenter Roeck
  2017-04-20 12:24                                 ` Heikki Krogerus
  0 siblings, 2 replies; 64+ messages in thread
From: Badhri Jagan Sridharan @ 2017-04-19 17:22 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Heikki Krogerus, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
> On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
>> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
>> <heikki.krogerus@linux.intel.com> wrote:
>> > Hi,
>> >
>> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
>> >> Hi Heikki,
>> >>
>> >> I have a question regarding the preferred_role node.
>> >>
>> >> +What:          /sys/class/typec/<port>/preferred_role
>> >> +Date:          March 2017
>> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> >> +Description:
>> >> +               The user space can notify the driver about the preferred role.
>> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
>> >> +               defined in USB Type-C specification, in the port drivers. By
>> >> +               default the preferred role should come from the platform.
>> >> +
>> >> +               Valid values: source, sink, none (to remove preference)
>> >>
>> >> What is the expected behavior when the userspace changes the
>> >> preferred_role node when the port is in connected state ?
>> >>
>> >> 1.  the state machine re-resolves the port roles right away based on
>> >> the new state machine in place ? (or)
>> >
>> > No! There are separate attributes for sending role swap requests.
>>
>> Right. But, that might not be helpful in cases when PD is not implemented.
>> and Implementing PD is not mandatory according the spec :/
>>
>> FYI quoting from the Type-C specification release(page 24),
>> role swaps are not limited to devices that only support PD.
>>
>> "Two independent set of mechanisms are defined to allow a USB Type-C
>> DRP to functionally swap power and data roles. When USB PD is
>> supported, power and data role swapping is performed as a subsequent
>> step following the initial connection process. For non-PD implementations,
>> power/data role swapping can optionally be dealt with as part of the initial
>> connection process."
>>
>> But, the current interface definition actually prevents current/data role
>> swaps for non-pd devices.
>>

> This is correct for the attribute definition, but it is not implemented
> that way. Writing the attribute is only read-only for non-DRP ports.

i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
is not TYPEC_PORT_DRP, is that what you are referring to ?

        if (port->typec_caps.type != TYPEC_PORT_DRP) {
                ret = -EINVAL;
                goto port_unlock;
        }

I do agree that this is actually correct. I am referring to the case
where port is
dual-role-power and dual-role-data but NOT PD capable.

> Given the standard, I would consider that to be intentional; it might
> make sense to update the description accordingly.
>
> How about implementing a mechanism in the dr_set and pr_set code in tcpm
> which would handle that situation ? Something along the line of
>
>         if (!port->pd_capable && connected && current role != desired role) {
>                 reset_port();
>                 goto done;
>         }

By "desired role" you are referring to preferred_role right ?

If so yes, That's a good idea as well and it might work as long as
type-c connector
class allows the call to reach tcpm code :) But the current connector
class code does
not allow that because the power_role and data_role nodes are defined that way.

port->cap->pd_revision and the port->pwr_opmode check in the below code
stub have to removed/refactored to make current_role/data_role writes to
reach the tcpm code.

+static ssize_t power_role_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct typec_port *port = to_typec_port(dev);
+ int ret = size;
+
+ if (!port->cap->pd_revision) {
+ dev_dbg(dev, "USB Power Delivery not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (!port->cap->pr_set) {
+ dev_dbg(dev, "power role swapping not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
+ dev_dbg(dev, "partner unable to swap power role\n");
+ return -EIO;
+ }
+
+ ret = sysfs_match_string(typec_roles, buf);
+ if (ret < 0)
+ return ret;
+
+ ret = port->cap->pr_set(port->cap, ret);
+ if (ret)
+ return ret;
+
+ return size;
+}

Thanks,
Badhri

>
> My current code doesn't handle the !pd_capable state, so I'll need to do
> something anyway.
>
> Thanks,
> Guenter
>
>> >
>> > The attribute will "enable" Try.SRC/SNK states, i.e. next time the
>> > state machine is executed, those states need to be considered.
>> > Changing the value of this attribute must not affect the current
>> > connection.
>> >
>> >> 2. Wait till the subsequent connect for resolving port roles based on the
>> >> new state machine.
>> >
>> > Yes.
>> >
>> >> For #1 to happen the policy_engine layer would have to reset the port
>> >> to resolve the port roles based on the (Try.SRC /Try.SNK/ Default)
>> >> new state machine preference.
>> >>
>> >> Say for example when two non-PD devices following none (default state
>> >> machine) are connected, the port role resolution is going to be random.
>> >> But, if the userspace in one of the devices later changes the
>> >> preferred_role to source, then that device is most likely to become source
>> >> if the Try.SRC state-machine is re-run.
>> >>
>> >> Does the above question fall under a policy decision ? If so, should there
>> >> be another node to say if the port roles have to re-resolved  based on the
>> >> new state machine right away ?
>> >
>> > I don't think we should even consider option #1, but just to be sure,
>> > Oliver, what do you say?
>>
>> Can we at least consider exposing a port_reset field so that the userspace
>> at least has an option to make the state machine to kick in right away with
>> a hard reset ?
>>
>> Please do consider. We can't expect all low-end phones and devices with
>> smaller form factors then phones to implement PD as it might be an overkill
>> for them.
>>
>> >
>> > I guess we need to say in the documentation explicitly that changing
>> > the value will not affect the current connection.
>> >
>> >
>> > Thanks,
>> >
>> > --
>> > heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-19 17:22                               ` Badhri Jagan Sridharan
@ 2017-04-19 19:29                                 ` Guenter Roeck
  2017-04-20 12:24                                 ` Heikki Krogerus
  1 sibling, 0 replies; 64+ messages in thread
From: Guenter Roeck @ 2017-04-19 19:29 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Heikki Krogerus, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
> >> <heikki.krogerus@linux.intel.com> wrote:
> >> > Hi,
> >> >
> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
> >> >> Hi Heikki,
> >> >>
> >> >> I have a question regarding the preferred_role node.
> >> >>
> >> >> +What:          /sys/class/typec/<port>/preferred_role
> >> >> +Date:          March 2017
> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
> >> >> +Description:
> >> >> +               The user space can notify the driver about the preferred role.
> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
> >> >> +               defined in USB Type-C specification, in the port drivers. By
> >> >> +               default the preferred role should come from the platform.
> >> >> +
> >> >> +               Valid values: source, sink, none (to remove preference)
> >> >>
> >> >> What is the expected behavior when the userspace changes the
> >> >> preferred_role node when the port is in connected state ?
> >> >>
> >> >> 1.  the state machine re-resolves the port roles right away based on
> >> >> the new state machine in place ? (or)
> >> >
> >> > No! There are separate attributes for sending role swap requests.
> >>
> >> Right. But, that might not be helpful in cases when PD is not implemented.
> >> and Implementing PD is not mandatory according the spec :/
> >>
> >> FYI quoting from the Type-C specification release(page 24),
> >> role swaps are not limited to devices that only support PD.
> >>
> >> "Two independent set of mechanisms are defined to allow a USB Type-C
> >> DRP to functionally swap power and data roles. When USB PD is
> >> supported, power and data role swapping is performed as a subsequent
> >> step following the initial connection process. For non-PD implementations,
> >> power/data role swapping can optionally be dealt with as part of the initial
> >> connection process."
> >>
> >> But, the current interface definition actually prevents current/data role
> >> swaps for non-pd devices.
> >>
> 
> > This is correct for the attribute definition, but it is not implemented
> > that way. Writing the attribute is only read-only for non-DRP ports.
> 
> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
> is not TYPEC_PORT_DRP, is that what you are referring to ?
> 
>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
>                 ret = -EINVAL;
>                 goto port_unlock;
>         }
> 
> I do agree that this is actually correct. I am referring to the case
> where port is
> dual-role-power and dual-role-data but NOT PD capable.
> 
At least in the current implementation of tcpm, the port type is reported
from low level drivers and does not change if the partner is not PD
capable. Port capabilities don't change if the partner is not PD capable,
and both are reported separately to the typec infrastructure.

> > Given the standard, I would consider that to be intentional; it might
> > make sense to update the description accordingly.
> >
> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
> > which would handle that situation ? Something along the line of
> >
> >         if (!port->pd_capable && connected && current role != desired role) {
> >                 reset_port();
> >                 goto done;
> >         }
> 
> By "desired role" you are referring to preferred_role right ?
> 
That is what it would boil down to, but that is really up to user space
to decide. User space would check if the reported role is the desired role,
and request a role change if it is not.
 
> If so yes, That's a good idea as well and it might work as long as
> type-c connector
> class allows the call to reach tcpm code :) But the current connector
> class code does
> not allow that because the power_role and data_role nodes are defined that way.
> 
> port->cap->pd_revision and the port->pwr_opmode check in the below code
> stub have to removed/refactored to make current_role/data_role writes to
> reach the tcpm code.
> 
> +static ssize_t power_role_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t size)
> +{
> + struct typec_port *port = to_typec_port(dev);
> + int ret = size;
> +
> + if (!port->cap->pd_revision) {
> + dev_dbg(dev, "USB Power Delivery not supported\n");
> + return -EOPNOTSUPP;
> + }
> +
> + if (!port->cap->pr_set) {
> + dev_dbg(dev, "power role swapping not supported\n");
> + return -EOPNOTSUPP;
> + }
> +
> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
> + dev_dbg(dev, "partner unable to swap power role\n");
> + return -EIO;
> + }
> +
Ah yes, you are right. Of course, you could request a data role change,
which doesn't have that restriction, at least not right now, but that
would not really be clean. Maybe it should be left to the low level
driver to do that check, or the check could be augmented to only
require pwr_opmode == TYPEC_PWR_MODE_PD if a preferred role is not set.

Thanks,
Guenter

> + ret = sysfs_match_string(typec_roles, buf);
> + if (ret < 0)
> + return ret;
> +
> + ret = port->cap->pr_set(port->cap, ret);
> + if (ret)
> + return ret;
> +
> + return size;
> +}
> 
> Thanks,
> Badhri
> 
> >
> > My current code doesn't handle the !pd_capable state, so I'll need to do
> > something anyway.
> >
> > Thanks,
> > Guenter
> >
> >> >
> >> > The attribute will "enable" Try.SRC/SNK states, i.e. next time the
> >> > state machine is executed, those states need to be considered.
> >> > Changing the value of this attribute must not affect the current
> >> > connection.
> >> >
> >> >> 2. Wait till the subsequent connect for resolving port roles based on the
> >> >> new state machine.
> >> >
> >> > Yes.
> >> >
> >> >> For #1 to happen the policy_engine layer would have to reset the port
> >> >> to resolve the port roles based on the (Try.SRC /Try.SNK/ Default)
> >> >> new state machine preference.
> >> >>
> >> >> Say for example when two non-PD devices following none (default state
> >> >> machine) are connected, the port role resolution is going to be random.
> >> >> But, if the userspace in one of the devices later changes the
> >> >> preferred_role to source, then that device is most likely to become source
> >> >> if the Try.SRC state-machine is re-run.
> >> >>
> >> >> Does the above question fall under a policy decision ? If so, should there
> >> >> be another node to say if the port roles have to re-resolved  based on the
> >> >> new state machine right away ?
> >> >
> >> > I don't think we should even consider option #1, but just to be sure,
> >> > Oliver, what do you say?
> >>
> >> Can we at least consider exposing a port_reset field so that the userspace
> >> at least has an option to make the state machine to kick in right away with
> >> a hard reset ?
> >>
> >> Please do consider. We can't expect all low-end phones and devices with
> >> smaller form factors then phones to implement PD as it might be an overkill
> >> for them.
> >>
> >> >
> >> > I guess we need to say in the documentation explicitly that changing
> >> > the value will not affect the current connection.
> >> >
> >> >
> >> > Thanks,
> >> >
> >> > --
> >> > heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-19 14:45                           ` Badhri Jagan Sridharan
  2017-04-19 15:14                             ` Guenter Roeck
@ 2017-04-20 11:55                             ` Heikki Krogerus
  1 sibling, 0 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-04-20 11:55 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Oliver Neukum, Guenter Roeck, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

Hi,

On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
> >> What is the expected behavior when the userspace changes the
> >> preferred_role node when the port is in connected state ?
> >>
> >> 1.  the state machine re-resolves the port roles right away based on
> >> the new state machine in place ? (or)
> >
> > No! There are separate attributes for sending role swap requests.
> 
> Right. But, that might not be helpful in cases when PD is not implemented.
> and Implementing PD is not mandatory according the spec :/
> 
> FYI quoting from the Type-C specification release(page 24),
> role swaps are not limited to devices that only support PD.
> 
> "Two independent set of mechanisms are defined to allow a USB Type-C
> DRP to functionally swap power and data roles. When USB PD is
> supported, power and data role swapping is performed as a subsequent
> step following the initial connection process. For non-PD implementations,
> power/data role swapping can optionally be dealt with as part of the initial
> connection process."
> 
> But, the current interface definition actually prevents current/data role
> swaps for non-pd devices.

No it doesn't. When USB PD is not supported, you can still use
data_role to swap the role. Of course, the lower level driver may
not support any role swapping in that case.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-19 17:22                               ` Badhri Jagan Sridharan
  2017-04-19 19:29                                 ` Guenter Roeck
@ 2017-04-20 12:24                                 ` Heikki Krogerus
  2017-04-20 19:46                                   ` Badhri Jagan Sridharan
  1 sibling, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-04-20 12:24 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Guenter Roeck, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
> >> <heikki.krogerus@linux.intel.com> wrote:
> >> > Hi,
> >> >
> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
> >> >> Hi Heikki,
> >> >>
> >> >> I have a question regarding the preferred_role node.
> >> >>
> >> >> +What:          /sys/class/typec/<port>/preferred_role
> >> >> +Date:          March 2017
> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
> >> >> +Description:
> >> >> +               The user space can notify the driver about the preferred role.
> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
> >> >> +               defined in USB Type-C specification, in the port drivers. By
> >> >> +               default the preferred role should come from the platform.
> >> >> +
> >> >> +               Valid values: source, sink, none (to remove preference)
> >> >>
> >> >> What is the expected behavior when the userspace changes the
> >> >> preferred_role node when the port is in connected state ?
> >> >>
> >> >> 1.  the state machine re-resolves the port roles right away based on
> >> >> the new state machine in place ? (or)
> >> >
> >> > No! There are separate attributes for sending role swap requests.
> >>
> >> Right. But, that might not be helpful in cases when PD is not implemented.
> >> and Implementing PD is not mandatory according the spec :/
> >>
> >> FYI quoting from the Type-C specification release(page 24),
> >> role swaps are not limited to devices that only support PD.
> >>
> >> "Two independent set of mechanisms are defined to allow a USB Type-C
> >> DRP to functionally swap power and data roles. When USB PD is
> >> supported, power and data role swapping is performed as a subsequent
> >> step following the initial connection process. For non-PD implementations,
> >> power/data role swapping can optionally be dealt with as part of the initial
> >> connection process."
> >>
> >> But, the current interface definition actually prevents current/data role
> >> swaps for non-pd devices.
> >>
> 
> > This is correct for the attribute definition, but it is not implemented
> > that way. Writing the attribute is only read-only for non-DRP ports.
> 
> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
> is not TYPEC_PORT_DRP, is that what you are referring to ?
> 
>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
>                 ret = -EINVAL;
>                 goto port_unlock;
>         }
> 
> I do agree that this is actually correct. I am referring to the case
> where port is
> dual-role-power and dual-role-data but NOT PD capable.
> 
> > Given the standard, I would consider that to be intentional; it might
> > make sense to update the description accordingly.
> >
> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
> > which would handle that situation ? Something along the line of
> >
> >         if (!port->pd_capable && connected && current role != desired role) {
> >                 reset_port();
> >                 goto done;
> >         }
> 
> By "desired role" you are referring to preferred_role right ?
> 
> If so yes, That's a good idea as well and it might work as long as
> type-c connector
> class allows the call to reach tcpm code :) But the current connector
> class code does
> not allow that because the power_role and data_role nodes are defined that way.

Well, the data_role does not limit the requests from reaching the low
level drivers, but..

> port->cap->pd_revision and the port->pwr_opmode check in the below code
> stub have to removed/refactored to make current_role/data_role writes to
> reach the tcpm code.
> 
> +static ssize_t power_role_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t size)
> +{
> + struct typec_port *port = to_typec_port(dev);
> + int ret = size;
> +
> + if (!port->cap->pd_revision) {
> + dev_dbg(dev, "USB Power Delivery not supported\n");
> + return -EOPNOTSUPP;
> + }
> +
> + if (!port->cap->pr_set) {
> + dev_dbg(dev, "power role swapping not supported\n");
> + return -EOPNOTSUPP;
> + }
> +
> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
> + dev_dbg(dev, "partner unable to swap power role\n");
> + return -EIO;
> + }
> +
> + ret = sysfs_match_string(typec_roles, buf);
> + if (ret < 0)
> + return ret;
> +
> + ret = port->cap->pr_set(port->cap, ret);
> + if (ret)
> + return ret;
> +
> + return size;
> +}

.. yes. The power_role_store() does indeed need to be refactored. The
PD requirement should only be applied to Type-C spec versions < 1.2,
or removed completely. I would be happy to leave the checks to the low
level drivers.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-20 12:24                                 ` Heikki Krogerus
@ 2017-04-20 19:46                                   ` Badhri Jagan Sridharan
  2017-04-21 12:12                                     ` Heikki Krogerus
  2017-04-21 14:27                                     ` Rajaram R
  0 siblings, 2 replies; 64+ messages in thread
From: Badhri Jagan Sridharan @ 2017-04-20 19:46 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: Guenter Roeck, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

Thanks for the responses :)

So seems like we have a plan.

In Type-C connector class the checks for TYPEC_PWR_MODE_PD
and pd_revision for both the port and the partner will be removed in
power_role_store and the data_role_store and will be delegated
to the low level drivers.

TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
current_role is not same as the preferred_role.

I am going to make changes in my local kernel code base to start
making the corresponding changes in userspace.
Should I post-back the local kernel changes or Heikki and Geunter
you are planning to upload them ?

Thanks for the support !!
Badhri.

On Thu, Apr 20, 2017 at 5:24 AM, Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
> On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
>> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
>> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
>> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
>> >> <heikki.krogerus@linux.intel.com> wrote:
>> >> > Hi,
>> >> >
>> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
>> >> >> Hi Heikki,
>> >> >>
>> >> >> I have a question regarding the preferred_role node.
>> >> >>
>> >> >> +What:          /sys/class/typec/<port>/preferred_role
>> >> >> +Date:          March 2017
>> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> >> >> +Description:
>> >> >> +               The user space can notify the driver about the preferred role.
>> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
>> >> >> +               defined in USB Type-C specification, in the port drivers. By
>> >> >> +               default the preferred role should come from the platform.
>> >> >> +
>> >> >> +               Valid values: source, sink, none (to remove preference)
>> >> >>
>> >> >> What is the expected behavior when the userspace changes the
>> >> >> preferred_role node when the port is in connected state ?
>> >> >>
>> >> >> 1.  the state machine re-resolves the port roles right away based on
>> >> >> the new state machine in place ? (or)
>> >> >
>> >> > No! There are separate attributes for sending role swap requests.
>> >>
>> >> Right. But, that might not be helpful in cases when PD is not implemented.
>> >> and Implementing PD is not mandatory according the spec :/
>> >>
>> >> FYI quoting from the Type-C specification release(page 24),
>> >> role swaps are not limited to devices that only support PD.
>> >>
>> >> "Two independent set of mechanisms are defined to allow a USB Type-C
>> >> DRP to functionally swap power and data roles. When USB PD is
>> >> supported, power and data role swapping is performed as a subsequent
>> >> step following the initial connection process. For non-PD implementations,
>> >> power/data role swapping can optionally be dealt with as part of the initial
>> >> connection process."
>> >>
>> >> But, the current interface definition actually prevents current/data role
>> >> swaps for non-pd devices.
>> >>
>>
>> > This is correct for the attribute definition, but it is not implemented
>> > that way. Writing the attribute is only read-only for non-DRP ports.
>>
>> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
>> is not TYPEC_PORT_DRP, is that what you are referring to ?
>>
>>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
>>                 ret = -EINVAL;
>>                 goto port_unlock;
>>         }
>>
>> I do agree that this is actually correct. I am referring to the case
>> where port is
>> dual-role-power and dual-role-data but NOT PD capable.
>>
>> > Given the standard, I would consider that to be intentional; it might
>> > make sense to update the description accordingly.
>> >
>> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
>> > which would handle that situation ? Something along the line of
>> >
>> >         if (!port->pd_capable && connected && current role != desired role) {
>> >                 reset_port();
>> >                 goto done;
>> >         }
>>
>> By "desired role" you are referring to preferred_role right ?
>>
>> If so yes, That's a good idea as well and it might work as long as
>> type-c connector
>> class allows the call to reach tcpm code :) But the current connector
>> class code does
>> not allow that because the power_role and data_role nodes are defined that way.
>
> Well, the data_role does not limit the requests from reaching the low
> level drivers, but..
>
>> port->cap->pd_revision and the port->pwr_opmode check in the below code
>> stub have to removed/refactored to make current_role/data_role writes to
>> reach the tcpm code.
>>
>> +static ssize_t power_role_store(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t size)
>> +{
>> + struct typec_port *port = to_typec_port(dev);
>> + int ret = size;
>> +
>> + if (!port->cap->pd_revision) {
>> + dev_dbg(dev, "USB Power Delivery not supported\n");
>> + return -EOPNOTSUPP;
>> + }
>> +
>> + if (!port->cap->pr_set) {
>> + dev_dbg(dev, "power role swapping not supported\n");
>> + return -EOPNOTSUPP;
>> + }
>> +
>> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
>> + dev_dbg(dev, "partner unable to swap power role\n");
>> + return -EIO;
>> + }
>> +
>> + ret = sysfs_match_string(typec_roles, buf);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = port->cap->pr_set(port->cap, ret);
>> + if (ret)
>> + return ret;
>> +
>> + return size;
>> +}
>
> .. yes. The power_role_store() does indeed need to be refactored. The
> PD requirement should only be applied to Type-C spec versions < 1.2,
> or removed completely. I would be happy to leave the checks to the low
> level drivers.
>
>
> Thanks,
>
> --
> heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-20 19:46                                   ` Badhri Jagan Sridharan
@ 2017-04-21 12:12                                     ` Heikki Krogerus
  2017-04-21 13:14                                       ` Guenter Roeck
  2017-04-21 14:27                                     ` Rajaram R
  1 sibling, 1 reply; 64+ messages in thread
From: Heikki Krogerus @ 2017-04-21 12:12 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Guenter Roeck, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

Hi,

On Thu, Apr 20, 2017 at 12:46:59PM -0700, Badhri Jagan Sridharan wrote:
> Thanks for the responses :)
> 
> So seems like we have a plan.
> 
> In Type-C connector class the checks for TYPEC_PWR_MODE_PD
> and pd_revision for both the port and the partner will be removed in
> power_role_store and the data_role_store and will be delegated
> to the low level drivers.
> 
> TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
> current_role is not same as the preferred_role.
> 
> I am going to make changes in my local kernel code base to start
> making the corresponding changes in userspace.
> Should I post-back the local kernel changes or Heikki and Geunter
> you are planning to upload them ?

Please send a patch for the class at least. I think the changes to the
tcpm can just be amended still at this point. That is of course up to
Guenter.


Thanks,

-- 
heikki

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-21 12:12                                     ` Heikki Krogerus
@ 2017-04-21 13:14                                       ` Guenter Roeck
  0 siblings, 0 replies; 64+ messages in thread
From: Guenter Roeck @ 2017-04-21 13:14 UTC (permalink / raw)
  To: Heikki Krogerus, Badhri Jagan Sridharan
  Cc: Oliver Neukum, Mats Karrman, Greg KH, Felipe Balbi, LKML, USB

On 04/21/2017 05:12 AM, Heikki Krogerus wrote:
> Hi,
>
> On Thu, Apr 20, 2017 at 12:46:59PM -0700, Badhri Jagan Sridharan wrote:
>> Thanks for the responses :)
>>
>> So seems like we have a plan.
>>
>> In Type-C connector class the checks for TYPEC_PWR_MODE_PD
>> and pd_revision for both the port and the partner will be removed in
>> power_role_store and the data_role_store and will be delegated
>> to the low level drivers.
>>
>> TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
>> current_role is not same as the preferred_role.
>>
>> I am going to make changes in my local kernel code base to start
>> making the corresponding changes in userspace.
>> Should I post-back the local kernel changes or Heikki and Geunter
>> you are planning to upload them ?
>
> Please send a patch for the class at least. I think the changes to the
> tcpm can just be amended still at this point. That is of course up to
> Guenter.
>

I'll try to make the changes and post a new version today.

Guenter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-20 19:46                                   ` Badhri Jagan Sridharan
  2017-04-21 12:12                                     ` Heikki Krogerus
@ 2017-04-21 14:27                                     ` Rajaram R
  2017-04-21 16:43                                       ` Guenter Roeck
  1 sibling, 1 reply; 64+ messages in thread
From: Rajaram R @ 2017-04-21 14:27 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Heikki Krogerus, Guenter Roeck, Oliver Neukum, Mats Karrman,
	Greg KH, Felipe Balbi, LKML, USB

On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
<badhri@google.com> wrote:
> Thanks for the responses :)
>
> So seems like we have a plan.
>
> In Type-C connector class the checks for TYPEC_PWR_MODE_PD
> and pd_revision for both the port and the partner will be removed in
> power_role_store and the data_role_store and will be delegated
> to the low level drivers.

It is important to remember what USB Type-C provide is mechanisms for
"TRYing" to become a particular role and not guaranteeing.

With what device combination do you fore see we could get the desired
role with this change ?


>
> TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
> current_role is not same as the preferred_role.
>
> I am going to make changes in my local kernel code base to start
> making the corresponding changes in userspace.
> Should I post-back the local kernel changes or Heikki and Geunter
> you are planning to upload them ?
>
> Thanks for the support !!
> Badhri.
>
> On Thu, Apr 20, 2017 at 5:24 AM, Heikki Krogerus
> <heikki.krogerus@linux.intel.com> wrote:
>> On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
>>> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
>>> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
>>> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
>>> >> <heikki.krogerus@linux.intel.com> wrote:
>>> >> > Hi,
>>> >> >
>>> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
>>> >> >> Hi Heikki,
>>> >> >>
>>> >> >> I have a question regarding the preferred_role node.
>>> >> >>
>>> >> >> +What:          /sys/class/typec/<port>/preferred_role
>>> >> >> +Date:          March 2017
>>> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>> >> >> +Description:
>>> >> >> +               The user space can notify the driver about the preferred role.
>>> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
>>> >> >> +               defined in USB Type-C specification, in the port drivers. By
>>> >> >> +               default the preferred role should come from the platform.
>>> >> >> +
>>> >> >> +               Valid values: source, sink, none (to remove preference)
>>> >> >>
>>> >> >> What is the expected behavior when the userspace changes the
>>> >> >> preferred_role node when the port is in connected state ?
>>> >> >>
>>> >> >> 1.  the state machine re-resolves the port roles right away based on
>>> >> >> the new state machine in place ? (or)
>>> >> >
>>> >> > No! There are separate attributes for sending role swap requests.
>>> >>
>>> >> Right. But, that might not be helpful in cases when PD is not implemented.
>>> >> and Implementing PD is not mandatory according the spec :/
>>> >>
>>> >> FYI quoting from the Type-C specification release(page 24),
>>> >> role swaps are not limited to devices that only support PD.
>>> >>
>>> >> "Two independent set of mechanisms are defined to allow a USB Type-C
>>> >> DRP to functionally swap power and data roles. When USB PD is
>>> >> supported, power and data role swapping is performed as a subsequent
>>> >> step following the initial connection process. For non-PD implementations,
>>> >> power/data role swapping can optionally be dealt with as part of the initial
>>> >> connection process."
>>> >>
>>> >> But, the current interface definition actually prevents current/data role
>>> >> swaps for non-pd devices.
>>> >>
>>>
>>> > This is correct for the attribute definition, but it is not implemented
>>> > that way. Writing the attribute is only read-only for non-DRP ports.
>>>
>>> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
>>> is not TYPEC_PORT_DRP, is that what you are referring to ?
>>>
>>>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
>>>                 ret = -EINVAL;
>>>                 goto port_unlock;
>>>         }
>>>
>>> I do agree that this is actually correct. I am referring to the case
>>> where port is
>>> dual-role-power and dual-role-data but NOT PD capable.
>>>
>>> > Given the standard, I would consider that to be intentional; it might
>>> > make sense to update the description accordingly.
>>> >
>>> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
>>> > which would handle that situation ? Something along the line of
>>> >
>>> >         if (!port->pd_capable && connected && current role != desired role) {
>>> >                 reset_port();
>>> >                 goto done;
>>> >         }
>>>
>>> By "desired role" you are referring to preferred_role right ?
>>>
>>> If so yes, That's a good idea as well and it might work as long as
>>> type-c connector
>>> class allows the call to reach tcpm code :) But the current connector
>>> class code does
>>> not allow that because the power_role and data_role nodes are defined that way.
>>
>> Well, the data_role does not limit the requests from reaching the low
>> level drivers, but..
>>
>>> port->cap->pd_revision and the port->pwr_opmode check in the below code
>>> stub have to removed/refactored to make current_role/data_role writes to
>>> reach the tcpm code.
>>>
>>> +static ssize_t power_role_store(struct device *dev,
>>> + struct device_attribute *attr,
>>> + const char *buf, size_t size)
>>> +{
>>> + struct typec_port *port = to_typec_port(dev);
>>> + int ret = size;
>>> +
>>> + if (!port->cap->pd_revision) {
>>> + dev_dbg(dev, "USB Power Delivery not supported\n");
>>> + return -EOPNOTSUPP;
>>> + }
>>> +
>>> + if (!port->cap->pr_set) {
>>> + dev_dbg(dev, "power role swapping not supported\n");
>>> + return -EOPNOTSUPP;
>>> + }
>>> +
>>> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
>>> + dev_dbg(dev, "partner unable to swap power role\n");
>>> + return -EIO;
>>> + }
>>> +
>>> + ret = sysfs_match_string(typec_roles, buf);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + ret = port->cap->pr_set(port->cap, ret);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return size;
>>> +}
>>
>> .. yes. The power_role_store() does indeed need to be refactored. The
>> PD requirement should only be applied to Type-C spec versions < 1.2,
>> or removed completely. I would be happy to leave the checks to the low
>> level drivers.
>>
>>
>> Thanks,
>>
>> --
>> heikki
> --
> 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] 64+ messages in thread

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-21 14:27                                     ` Rajaram R
@ 2017-04-21 16:43                                       ` Guenter Roeck
  2017-04-22  9:23                                         ` Rajaram R
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-04-21 16:43 UTC (permalink / raw)
  To: Rajaram R
  Cc: Badhri Jagan Sridharan, Heikki Krogerus, Oliver Neukum,
	Mats Karrman, Greg KH, Felipe Balbi, LKML, USB

On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
> <badhri@google.com> wrote:
> > Thanks for the responses :)
> >
> > So seems like we have a plan.
> >
> > In Type-C connector class the checks for TYPEC_PWR_MODE_PD
> > and pd_revision for both the port and the partner will be removed in
> > power_role_store and the data_role_store and will be delegated
> > to the low level drivers.
> 
> It is important to remember what USB Type-C provide is mechanisms for
> "TRYing" to become a particular role and not guaranteeing.
> 
> With what device combination do you fore see we could get the desired
> role with this change ?
> 

If the partner is not PD capable, if a preferred role is specified, 
if the current cole does not match the preferred role, and if the request
is to set the role to match the preferred role, I think it is reasonable
to expect that re-establishing the connection would accomplish that if the
partner supports it.

Of course, that won't change anything if the partner does not support the
desired role, but it is better than doing nothing. This is also comparable
to requesting a role change from the partner if it does support PD.

Do you have a better idea ?

Thanks,
Guenter

> 
> >
> > TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
> > current_role is not same as the preferred_role.
> >

... if the partner is not PD capable.

> > I am going to make changes in my local kernel code base to start
> > making the corresponding changes in userspace.
> > Should I post-back the local kernel changes or Heikki and Geunter
> > you are planning to upload them ?
> >
> > Thanks for the support !!
> > Badhri.
> >
> > On Thu, Apr 20, 2017 at 5:24 AM, Heikki Krogerus
> > <heikki.krogerus@linux.intel.com> wrote:
> >> On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
> >>> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
> >>> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
> >>> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
> >>> >> <heikki.krogerus@linux.intel.com> wrote:
> >>> >> > Hi,
> >>> >> >
> >>> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
> >>> >> >> Hi Heikki,
> >>> >> >>
> >>> >> >> I have a question regarding the preferred_role node.
> >>> >> >>
> >>> >> >> +What:          /sys/class/typec/<port>/preferred_role
> >>> >> >> +Date:          March 2017
> >>> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
> >>> >> >> +Description:
> >>> >> >> +               The user space can notify the driver about the preferred role.
> >>> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
> >>> >> >> +               defined in USB Type-C specification, in the port drivers. By
> >>> >> >> +               default the preferred role should come from the platform.
> >>> >> >> +
> >>> >> >> +               Valid values: source, sink, none (to remove preference)
> >>> >> >>
> >>> >> >> What is the expected behavior when the userspace changes the
> >>> >> >> preferred_role node when the port is in connected state ?
> >>> >> >>
> >>> >> >> 1.  the state machine re-resolves the port roles right away based on
> >>> >> >> the new state machine in place ? (or)
> >>> >> >
> >>> >> > No! There are separate attributes for sending role swap requests.
> >>> >>
> >>> >> Right. But, that might not be helpful in cases when PD is not implemented.
> >>> >> and Implementing PD is not mandatory according the spec :/
> >>> >>
> >>> >> FYI quoting from the Type-C specification release(page 24),
> >>> >> role swaps are not limited to devices that only support PD.
> >>> >>
> >>> >> "Two independent set of mechanisms are defined to allow a USB Type-C
> >>> >> DRP to functionally swap power and data roles. When USB PD is
> >>> >> supported, power and data role swapping is performed as a subsequent
> >>> >> step following the initial connection process. For non-PD implementations,
> >>> >> power/data role swapping can optionally be dealt with as part of the initial
> >>> >> connection process."
> >>> >>
> >>> >> But, the current interface definition actually prevents current/data role
> >>> >> swaps for non-pd devices.
> >>> >>
> >>>
> >>> > This is correct for the attribute definition, but it is not implemented
> >>> > that way. Writing the attribute is only read-only for non-DRP ports.
> >>>
> >>> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
> >>> is not TYPEC_PORT_DRP, is that what you are referring to ?
> >>>
> >>>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
> >>>                 ret = -EINVAL;
> >>>                 goto port_unlock;
> >>>         }
> >>>
> >>> I do agree that this is actually correct. I am referring to the case
> >>> where port is
> >>> dual-role-power and dual-role-data but NOT PD capable.
> >>>
> >>> > Given the standard, I would consider that to be intentional; it might
> >>> > make sense to update the description accordingly.
> >>> >
> >>> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
> >>> > which would handle that situation ? Something along the line of
> >>> >
> >>> >         if (!port->pd_capable && connected && current role != desired role) {
> >>> >                 reset_port();
> >>> >                 goto done;
> >>> >         }
> >>>
> >>> By "desired role" you are referring to preferred_role right ?
> >>>
> >>> If so yes, That's a good idea as well and it might work as long as
> >>> type-c connector
> >>> class allows the call to reach tcpm code :) But the current connector
> >>> class code does
> >>> not allow that because the power_role and data_role nodes are defined that way.
> >>
> >> Well, the data_role does not limit the requests from reaching the low
> >> level drivers, but..
> >>
> >>> port->cap->pd_revision and the port->pwr_opmode check in the below code
> >>> stub have to removed/refactored to make current_role/data_role writes to
> >>> reach the tcpm code.
> >>>
> >>> +static ssize_t power_role_store(struct device *dev,
> >>> + struct device_attribute *attr,
> >>> + const char *buf, size_t size)
> >>> +{
> >>> + struct typec_port *port = to_typec_port(dev);
> >>> + int ret = size;
> >>> +
> >>> + if (!port->cap->pd_revision) {
> >>> + dev_dbg(dev, "USB Power Delivery not supported\n");
> >>> + return -EOPNOTSUPP;
> >>> + }
> >>> +
> >>> + if (!port->cap->pr_set) {
> >>> + dev_dbg(dev, "power role swapping not supported\n");
> >>> + return -EOPNOTSUPP;
> >>> + }
> >>> +
> >>> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
> >>> + dev_dbg(dev, "partner unable to swap power role\n");
> >>> + return -EIO;
> >>> + }
> >>> +
> >>> + ret = sysfs_match_string(typec_roles, buf);
> >>> + if (ret < 0)
> >>> + return ret;
> >>> +
> >>> + ret = port->cap->pr_set(port->cap, ret);
> >>> + if (ret)
> >>> + return ret;
> >>> +
> >>> + return size;
> >>> +}
> >>
> >> .. yes. The power_role_store() does indeed need to be refactored. The
> >> PD requirement should only be applied to Type-C spec versions < 1.2,
> >> or removed completely. I would be happy to leave the checks to the low
> >> level drivers.
> >>
> >>
> >> Thanks,
> >>
> >> --
> >> heikki
> > --
> > 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] 64+ messages in thread

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-21 16:43                                       ` Guenter Roeck
@ 2017-04-22  9:23                                         ` Rajaram R
  2017-04-24 17:50                                           ` Badhri Jagan Sridharan
  0 siblings, 1 reply; 64+ messages in thread
From: Rajaram R @ 2017-04-22  9:23 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Badhri Jagan Sridharan, Heikki Krogerus, Oliver Neukum,
	Mats Karrman, Greg KH, Felipe Balbi, LKML, USB

On Fri, Apr 21, 2017 at 10:13 PM, Guenter Roeck <linux@roeck-us.net> wrote:
> On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
>> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
>> <badhri@google.com> wrote:
>> > Thanks for the responses :)
>> >
>> > So seems like we have a plan.
>> >
>> > In Type-C connector class the checks for TYPEC_PWR_MODE_PD
>> > and pd_revision for both the port and the partner will be removed in
>> > power_role_store and the data_role_store and will be delegated
>> > to the low level drivers.
>>
>> It is important to remember what USB Type-C provide is mechanisms for
>> "TRYing" to become a particular role and not guaranteeing.
>>
>> With what device combination do you fore see we could get the desired
>> role with this change ?
>>
>
> If the partner is not PD capable, if a preferred role is specified,
> if the current cole does not match the preferred role, and if the request
> is to set the role to match the preferred role, I think it is reasonable
> to expect that re-establishing the connection would accomplish that if the
> partner supports it.
>
In this context I believe we have two different inputs as follows:

/sys/class/typec/<port>/supported_power_roles
/sys/class/typec/<port>/preferred_role

The need of preferred role is required when DRP is set in
supported_power_roles option.
Ideally a battery powered device will TRY to be SNK and a a/c plugged
device will TRY to be SRC

We need to understand which non-PD device will set to DRP? In the
current ecosystem all legacy devices
will sit behind adapters which either present an Rp or Rd.

If it is a power adapter in 5V range can either present Rp or DRP with
TRY.SRC and there is no role swap requirement.

If it is a laptop port or similar with non-PD (??) DRP  there is no
guaranteed role swap in a non-PD mode.
So we need to understand what non PD device will fit into this scenario ?

> Of course, that won't change anything if the partner does not support the
> desired role, but it is better than doing nothing. This is also comparable
> to requesting a role change from the partner if it does support PD.

All I am highlighting is that we can only TRY and there is no
guaranteed role swap with Type-C

> Do you have a better idea ?
>
If need a guaranteed role in a non-PD mode we need to set the required
role in supported_power_roles.
An understanding of scenario will help take better approach.

> Thanks,
> Guenter
>
>>
>> >
>> > TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
>> > current_role is not same as the preferred_role.
>> >
>
> ... if the partner is not PD capable.
>
>> > I am going to make changes in my local kernel code base to start
>> > making the corresponding changes in userspace.
>> > Should I post-back the local kernel changes or Heikki and Geunter
>> > you are planning to upload them ?
>> >
>> > Thanks for the support !!
>> > Badhri.
>> >
>> > On Thu, Apr 20, 2017 at 5:24 AM, Heikki Krogerus
>> > <heikki.krogerus@linux.intel.com> wrote:
>> >> On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
>> >>> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
>> >>> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
>> >>> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
>> >>> >> <heikki.krogerus@linux.intel.com> wrote:
>> >>> >> > Hi,
>> >>> >> >
>> >>> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
>> >>> >> >> Hi Heikki,
>> >>> >> >>
>> >>> >> >> I have a question regarding the preferred_role node.
>> >>> >> >>
>> >>> >> >> +What:          /sys/class/typec/<port>/preferred_role
>> >>> >> >> +Date:          March 2017
>> >>> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> >>> >> >> +Description:
>> >>> >> >> +               The user space can notify the driver about the preferred role.
>> >>> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
>> >>> >> >> +               defined in USB Type-C specification, in the port drivers. By
>> >>> >> >> +               default the preferred role should come from the platform.
>> >>> >> >> +
>> >>> >> >> +               Valid values: source, sink, none (to remove preference)
>> >>> >> >>
>> >>> >> >> What is the expected behavior when the userspace changes the
>> >>> >> >> preferred_role node when the port is in connected state ?
>> >>> >> >>
>> >>> >> >> 1.  the state machine re-resolves the port roles right away based on
>> >>> >> >> the new state machine in place ? (or)
>> >>> >> >
>> >>> >> > No! There are separate attributes for sending role swap requests.
>> >>> >>
>> >>> >> Right. But, that might not be helpful in cases when PD is not implemented.
>> >>> >> and Implementing PD is not mandatory according the spec :/
>> >>> >>
>> >>> >> FYI quoting from the Type-C specification release(page 24),
>> >>> >> role swaps are not limited to devices that only support PD.
>> >>> >>
>> >>> >> "Two independent set of mechanisms are defined to allow a USB Type-C
>> >>> >> DRP to functionally swap power and data roles. When USB PD is
>> >>> >> supported, power and data role swapping is performed as a subsequent
>> >>> >> step following the initial connection process. For non-PD implementations,
>> >>> >> power/data role swapping can optionally be dealt with as part of the initial
>> >>> >> connection process."
>> >>> >>
>> >>> >> But, the current interface definition actually prevents current/data role
>> >>> >> swaps for non-pd devices.
>> >>> >>
>> >>>
>> >>> > This is correct for the attribute definition, but it is not implemented
>> >>> > that way. Writing the attribute is only read-only for non-DRP ports.
>> >>>
>> >>> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
>> >>> is not TYPEC_PORT_DRP, is that what you are referring to ?
>> >>>
>> >>>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
>> >>>                 ret = -EINVAL;
>> >>>                 goto port_unlock;
>> >>>         }
>> >>>
>> >>> I do agree that this is actually correct. I am referring to the case
>> >>> where port is
>> >>> dual-role-power and dual-role-data but NOT PD capable.
>> >>>
>> >>> > Given the standard, I would consider that to be intentional; it might
>> >>> > make sense to update the description accordingly.
>> >>> >
>> >>> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
>> >>> > which would handle that situation ? Something along the line of
>> >>> >
>> >>> >         if (!port->pd_capable && connected && current role != desired role) {
>> >>> >                 reset_port();
>> >>> >                 goto done;
>> >>> >         }
>> >>>
>> >>> By "desired role" you are referring to preferred_role right ?
>> >>>
>> >>> If so yes, That's a good idea as well and it might work as long as
>> >>> type-c connector
>> >>> class allows the call to reach tcpm code :) But the current connector
>> >>> class code does
>> >>> not allow that because the power_role and data_role nodes are defined that way.
>> >>
>> >> Well, the data_role does not limit the requests from reaching the low
>> >> level drivers, but..
>> >>
>> >>> port->cap->pd_revision and the port->pwr_opmode check in the below code
>> >>> stub have to removed/refactored to make current_role/data_role writes to
>> >>> reach the tcpm code.
>> >>>
>> >>> +static ssize_t power_role_store(struct device *dev,
>> >>> + struct device_attribute *attr,
>> >>> + const char *buf, size_t size)
>> >>> +{
>> >>> + struct typec_port *port = to_typec_port(dev);
>> >>> + int ret = size;
>> >>> +
>> >>> + if (!port->cap->pd_revision) {
>> >>> + dev_dbg(dev, "USB Power Delivery not supported\n");
>> >>> + return -EOPNOTSUPP;
>> >>> + }
>> >>> +
>> >>> + if (!port->cap->pr_set) {
>> >>> + dev_dbg(dev, "power role swapping not supported\n");
>> >>> + return -EOPNOTSUPP;
>> >>> + }
>> >>> +
>> >>> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
>> >>> + dev_dbg(dev, "partner unable to swap power role\n");
>> >>> + return -EIO;
>> >>> + }
>> >>> +
>> >>> + ret = sysfs_match_string(typec_roles, buf);
>> >>> + if (ret < 0)
>> >>> + return ret;
>> >>> +
>> >>> + ret = port->cap->pr_set(port->cap, ret);
>> >>> + if (ret)
>> >>> + return ret;
>> >>> +
>> >>> + return size;
>> >>> +}
>> >>
>> >> .. yes. The power_role_store() does indeed need to be refactored. The
>> >> PD requirement should only be applied to Type-C spec versions < 1.2,
>> >> or removed completely. I would be happy to leave the checks to the low
>> >> level drivers.
>> >>
>> >>
>> >> Thanks,
>> >>
>> >> --
>> >> heikki
>> > --
>> > 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] 64+ messages in thread

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-22  9:23                                         ` Rajaram R
@ 2017-04-24 17:50                                           ` Badhri Jagan Sridharan
  2017-04-25  8:26                                             ` Rajaram R
  0 siblings, 1 reply; 64+ messages in thread
From: Badhri Jagan Sridharan @ 2017-04-24 17:50 UTC (permalink / raw)
  To: Rajaram R
  Cc: Guenter Roeck, Heikki Krogerus, Oliver Neukum, Mats Karrman,
	Greg KH, Felipe Balbi, LKML, USB

On Sat, Apr 22, 2017 at 2:23 AM, Rajaram R <rajaram.officemail@gmail.com> wrote:
> On Fri, Apr 21, 2017 at 10:13 PM, Guenter Roeck <linux@roeck-us.net> wrote:
>> On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
>>> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
>>> <badhri@google.com> wrote:
>>> > Thanks for the responses :)
>>> >
>>> > So seems like we have a plan.
>>> >
>>> > In Type-C connector class the checks for TYPEC_PWR_MODE_PD
>>> > and pd_revision for both the port and the partner will be removed in
>>> > power_role_store and the data_role_store and will be delegated
>>> > to the low level drivers.
>>>
>>> It is important to remember what USB Type-C provide is mechanisms for
>>> "TRYing" to become a particular role and not guaranteeing.
>>>
>>> With what device combination do you fore see we could get the desired
>>> role with this change ?
>>>
>>
>> If the partner is not PD capable, if a preferred role is specified,
>> if the current cole does not match the preferred role, and if the request
>> is to set the role to match the preferred role, I think it is reasonable
>> to expect that re-establishing the connection would accomplish that if the
>> partner supports it.
>>
> In this context I believe we have two different inputs as follows:
>
> /sys/class/typec/<port>/supported_power_roles
> /sys/class/typec/<port>/preferred_role
>
> The need of preferred role is required when DRP is set in
> supported_power_roles option.
> Ideally a battery powered device will TRY to be SNK and a a/c plugged
> device will TRY to be SRC
>
> We need to understand which non-PD device will set to DRP? In the

Android Phones (actually it could be any phone which has a type-c port)
since it can act as usb gadget (when connected to PC) or Usb host
when connected to peripherals such as thumb drives, keyboard etc.
Phones with smaller form factors might be thermally limited to charge
above 15W, therefore supporting PD might be an overkill for them.

> current ecosystem all legacy devices
> will sit behind adapters which either present an Rp or Rd.
>
> If it is a power adapter in 5V range can either present Rp or DRP with
> TRY.SRC and there is no role swap requirement.
>
> If it is a laptop port or similar with non-PD (??) DRP  there is no
> guaranteed role swap in a non-PD mode.

This is true, but following a Try.SRC or Try.SNK state machine can
increase the chances of landing in the desired role/preferred role.

> So we need to understand what non PD device will fit into this scenario ?
Answered above.

>
>> Of course, that won't change anything if the partner does not support the
>> desired role, but it is better than doing nothing. This is also comparable
>> to requesting a role change from the partner if it does support PD.
>
> All I am highlighting is that we can only TRY and there is no
> guaranteed role swap with Type-C
>
>> Do you have a better idea ?
>>
> If need a guaranteed role in a non-PD mode we need to set the required
> role in supported_power_roles.
> An understanding of scenario will help take better approach.

The current Type-c connector class interface defines the support_*_roles as
read-only nodes. Leaving that apart, I think what you are trying to say is that
instead of running through the state machine again by switching to
Try.SRC or Try.SNK, you are suggesting that switch from DRP to source/host
(or) sink/device to make sure that CC is either pulled up through Rp or
grounded through Rd so that it increases the chances of settling in the desired
role. I do agree this, but, there is a pitfall here. Say when a DRP is
connected to
a pure sink/device, when the DRP switches to being a pure sink as well, then
the port roles would not resolve at all as both would be asserting Rd on CC and
therefore it might not be possible to detect a disconnect unless we have
a VCONN powered cable. Following Try.SRC, Try.SNK state machine actually
takes care of this for you. When in Try.SRC or Try.SNK state, CC would either
be pulled up or down for a specific amount of time (tCCDebounce) to check if the
port partner is capable of switching to another role. If no port
resolution happens
within the timer expiry, the state machine forces the port into the
other role and
port resolution would eventually happen. IMHO So in short it is more safer to
switch to between Try.SRC and Try.SNK state machine to land in a preferred role
rather than switching a DRP to source or sink.

>
>> Thanks,
>> Guenter
>>
>>>
>>> >
>>> > TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
>>> > current_role is not same as the preferred_role.
>>> >
>>
>> ... if the partner is not PD capable.
>>
>>> > I am going to make changes in my local kernel code base to start
>>> > making the corresponding changes in userspace.
>>> > Should I post-back the local kernel changes or Heikki and Geunter
>>> > you are planning to upload them ?
>>> >
>>> > Thanks for the support !!
>>> > Badhri.
>>> >
>>> > On Thu, Apr 20, 2017 at 5:24 AM, Heikki Krogerus
>>> > <heikki.krogerus@linux.intel.com> wrote:
>>> >> On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
>>> >>> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
>>> >>> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
>>> >>> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
>>> >>> >> <heikki.krogerus@linux.intel.com> wrote:
>>> >>> >> > Hi,
>>> >>> >> >
>>> >>> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
>>> >>> >> >> Hi Heikki,
>>> >>> >> >>
>>> >>> >> >> I have a question regarding the preferred_role node.
>>> >>> >> >>
>>> >>> >> >> +What:          /sys/class/typec/<port>/preferred_role
>>> >>> >> >> +Date:          March 2017
>>> >>> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>> >>> >> >> +Description:
>>> >>> >> >> +               The user space can notify the driver about the preferred role.
>>> >>> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
>>> >>> >> >> +               defined in USB Type-C specification, in the port drivers. By
>>> >>> >> >> +               default the preferred role should come from the platform.
>>> >>> >> >> +
>>> >>> >> >> +               Valid values: source, sink, none (to remove preference)
>>> >>> >> >>
>>> >>> >> >> What is the expected behavior when the userspace changes the
>>> >>> >> >> preferred_role node when the port is in connected state ?
>>> >>> >> >>
>>> >>> >> >> 1.  the state machine re-resolves the port roles right away based on
>>> >>> >> >> the new state machine in place ? (or)
>>> >>> >> >
>>> >>> >> > No! There are separate attributes for sending role swap requests.
>>> >>> >>
>>> >>> >> Right. But, that might not be helpful in cases when PD is not implemented.
>>> >>> >> and Implementing PD is not mandatory according the spec :/
>>> >>> >>
>>> >>> >> FYI quoting from the Type-C specification release(page 24),
>>> >>> >> role swaps are not limited to devices that only support PD.
>>> >>> >>
>>> >>> >> "Two independent set of mechanisms are defined to allow a USB Type-C
>>> >>> >> DRP to functionally swap power and data roles. When USB PD is
>>> >>> >> supported, power and data role swapping is performed as a subsequent
>>> >>> >> step following the initial connection process. For non-PD implementations,
>>> >>> >> power/data role swapping can optionally be dealt with as part of the initial
>>> >>> >> connection process."
>>> >>> >>
>>> >>> >> But, the current interface definition actually prevents current/data role
>>> >>> >> swaps for non-pd devices.
>>> >>> >>
>>> >>>
>>> >>> > This is correct for the attribute definition, but it is not implemented
>>> >>> > that way. Writing the attribute is only read-only for non-DRP ports.
>>> >>>
>>> >>> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
>>> >>> is not TYPEC_PORT_DRP, is that what you are referring to ?
>>> >>>
>>> >>>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
>>> >>>                 ret = -EINVAL;
>>> >>>                 goto port_unlock;
>>> >>>         }
>>> >>>
>>> >>> I do agree that this is actually correct. I am referring to the case
>>> >>> where port is
>>> >>> dual-role-power and dual-role-data but NOT PD capable.
>>> >>>
>>> >>> > Given the standard, I would consider that to be intentional; it might
>>> >>> > make sense to update the description accordingly.
>>> >>> >
>>> >>> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
>>> >>> > which would handle that situation ? Something along the line of
>>> >>> >
>>> >>> >         if (!port->pd_capable && connected && current role != desired role) {
>>> >>> >                 reset_port();
>>> >>> >                 goto done;
>>> >>> >         }
>>> >>>
>>> >>> By "desired role" you are referring to preferred_role right ?
>>> >>>
>>> >>> If so yes, That's a good idea as well and it might work as long as
>>> >>> type-c connector
>>> >>> class allows the call to reach tcpm code :) But the current connector
>>> >>> class code does
>>> >>> not allow that because the power_role and data_role nodes are defined that way.
>>> >>
>>> >> Well, the data_role does not limit the requests from reaching the low
>>> >> level drivers, but..
>>> >>
>>> >>> port->cap->pd_revision and the port->pwr_opmode check in the below code
>>> >>> stub have to removed/refactored to make current_role/data_role writes to
>>> >>> reach the tcpm code.
>>> >>>
>>> >>> +static ssize_t power_role_store(struct device *dev,
>>> >>> + struct device_attribute *attr,
>>> >>> + const char *buf, size_t size)
>>> >>> +{
>>> >>> + struct typec_port *port = to_typec_port(dev);
>>> >>> + int ret = size;
>>> >>> +
>>> >>> + if (!port->cap->pd_revision) {
>>> >>> + dev_dbg(dev, "USB Power Delivery not supported\n");
>>> >>> + return -EOPNOTSUPP;
>>> >>> + }
>>> >>> +
>>> >>> + if (!port->cap->pr_set) {
>>> >>> + dev_dbg(dev, "power role swapping not supported\n");
>>> >>> + return -EOPNOTSUPP;
>>> >>> + }
>>> >>> +
>>> >>> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
>>> >>> + dev_dbg(dev, "partner unable to swap power role\n");
>>> >>> + return -EIO;
>>> >>> + }
>>> >>> +
>>> >>> + ret = sysfs_match_string(typec_roles, buf);
>>> >>> + if (ret < 0)
>>> >>> + return ret;
>>> >>> +
>>> >>> + ret = port->cap->pr_set(port->cap, ret);
>>> >>> + if (ret)
>>> >>> + return ret;
>>> >>> +
>>> >>> + return size;
>>> >>> +}
>>> >>
>>> >> .. yes. The power_role_store() does indeed need to be refactored. The
>>> >> PD requirement should only be applied to Type-C spec versions < 1.2,
>>> >> or removed completely. I would be happy to leave the checks to the low
>>> >> level drivers.
>>> >>
>>> >>
>>> >> Thanks,
>>> >>
>>> >> --
>>> >> heikki
>>> > --
>>> > 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] 64+ messages in thread

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-24 17:50                                           ` Badhri Jagan Sridharan
@ 2017-04-25  8:26                                             ` Rajaram R
  2017-04-25 14:10                                               ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Rajaram R @ 2017-04-25  8:26 UTC (permalink / raw)
  To: Badhri Jagan Sridharan
  Cc: Guenter Roeck, Heikki Krogerus, Oliver Neukum, Mats Karrman,
	Greg KH, Felipe Balbi, LKML, USB

On Mon, Apr 24, 2017 at 11:20 PM, Badhri Jagan Sridharan
<badhri@google.com> wrote:
> On Sat, Apr 22, 2017 at 2:23 AM, Rajaram R <rajaram.officemail@gmail.com> wrote:
>> On Fri, Apr 21, 2017 at 10:13 PM, Guenter Roeck <linux@roeck-us.net> wrote:
>>> On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
>>>> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
>>>> <badhri@google.com> wrote:
>>>> > Thanks for the responses :)
>>>> >
>>>> > So seems like we have a plan.
>>>> >
>>>> > In Type-C connector class the checks for TYPEC_PWR_MODE_PD
>>>> > and pd_revision for both the port and the partner will be removed in
>>>> > power_role_store and the data_role_store and will be delegated
>>>> > to the low level drivers.
>>>>
>>>> It is important to remember what USB Type-C provide is mechanisms for
>>>> "TRYing" to become a particular role and not guaranteeing.
>>>>
>>>> With what device combination do you fore see we could get the desired
>>>> role with this change ?
>>>>
>>>
>>> If the partner is not PD capable, if a preferred role is specified,
>>> if the current cole does not match the preferred role, and if the request
>>> is to set the role to match the preferred role, I think it is reasonable
>>> to expect that re-establishing the connection would accomplish that if the
>>> partner supports it.
>>>
>> In this context I believe we have two different inputs as follows:
>>
>> /sys/class/typec/<port>/supported_power_roles
>> /sys/class/typec/<port>/preferred_role
>>
>> The need of preferred role is required when DRP is set in
>> supported_power_roles option.
>> Ideally a battery powered device will TRY to be SNK and a a/c plugged
>> device will TRY to be SRC
>>
>> We need to understand which non-PD device will set to DRP? In the
>
> Android Phones (actually it could be any phone which has a type-c port)
> since it can act as usb gadget (when connected to PC) or Usb host
> when connected to peripherals such as thumb drives, keyboard etc.
> Phones with smaller form factors might be thermally limited to charge
> above 15W, therefore supporting PD might be an overkill for them.
>
>> current ecosystem all legacy devices
>> will sit behind adapters which either present an Rp or Rd.
>>
>> If it is a power adapter in 5V range can either present Rp or DRP with
>> TRY.SRC and there is no role swap requirement.
>>
>> If it is a laptop port or similar with non-PD (??) DRP  there is no
>> guaranteed role swap in a non-PD mode.
>
> This is true, but following a Try.SRC or Try.SNK state machine can
> increase the chances of landing in the desired role/preferred role.

Agree and as indicated it increases only chances.

>
>> So we need to understand what non PD device will fit into this scenario ?
> Answered above.
>
>>
>>> Of course, that won't change anything if the partner does not support the
>>> desired role, but it is better than doing nothing. This is also comparable
>>> to requesting a role change from the partner if it does support PD.
>>
>> All I am highlighting is that we can only TRY and there is no
>> guaranteed role swap with Type-C
>>
>>> Do you have a better idea ?
>>>
>> If need a guaranteed role in a non-PD mode we need to set the required
>> role in supported_power_roles.
>> An understanding of scenario will help take better approach.
>
> The current Type-c connector class interface defines the support_*_roles as
> read-only nodes. Leaving that apart, I think what you are trying to say is that
> instead of running through the state machine again by switching to
> Try.SRC or Try.SNK, you are suggesting that switch from DRP to source/host
> (or) sink/device to make sure that CC is either pulled up through Rp or
> grounded through Rd so that it increases the chances of settling in the desired
> role. I do agree this, but, there is a pitfall here. Say when a DRP is
> connected to
> a pure sink/device, when the DRP switches to being a pure sink as well, then
> the port roles would not resolve at all as both would be asserting Rd on CC and

If it is a pure SNK(presenting Rd), there is no conflict and a DRP be
it TRY SRC or TRY SNK
will endup as SRC.


> therefore it might not be possible to detect a disconnect unless we have
> a VCONN powered cable. Following Try.SRC, Try.SNK state machine actually

VConn does not play any role in detection.

> takes care of this for you. When in Try.SRC or Try.SNK state, CC would either
> be pulled up or down for a specific amount of time (tCCDebounce) to check if the
> port partner is capable of switching to another role. If no port
> resolution happens
> within the timer expiry, the state machine forces the port into the
> other role and
> port resolution would eventually happen. IMHO So in short it is more safer to
> switch to between Try.SRC and Try.SNK state machine to land in a preferred role
> rather than switching a DRP to source or sink.

The only scenario i can think of now is  when connecting two mobiles
back to back. In this case if both devices
uses the same logic of switch to between Try.SRC and Try.SNK you will
not get desired result.

I guess the way we choose USB Classes(MTP or PTP or Tethering) could
be an approach where user know what he/she need.

>
>>
>>> Thanks,
>>> Guenter
>>>
>>>>
>>>> >
>>>> > TCPM code will issue hard reset in tcpm_dr_set and tcpm_pr_set if
>>>> > current_role is not same as the preferred_role.
>>>> >
>>>
>>> ... if the partner is not PD capable.
>>>
>>>> > I am going to make changes in my local kernel code base to start
>>>> > making the corresponding changes in userspace.
>>>> > Should I post-back the local kernel changes or Heikki and Geunter
>>>> > you are planning to upload them ?
>>>> >
>>>> > Thanks for the support !!
>>>> > Badhri.
>>>> >
>>>> > On Thu, Apr 20, 2017 at 5:24 AM, Heikki Krogerus
>>>> > <heikki.krogerus@linux.intel.com> wrote:
>>>> >> On Wed, Apr 19, 2017 at 10:22:47AM -0700, Badhri Jagan Sridharan wrote:
>>>> >>> On Wed, Apr 19, 2017 at 8:14 AM, Guenter Roeck <linux@roeck-us.net> wrote:
>>>> >>> > On Wed, Apr 19, 2017 at 07:45:00AM -0700, Badhri Jagan Sridharan wrote:
>>>> >>> >> On Wed, Apr 19, 2017 at 4:23 AM, Heikki Krogerus
>>>> >>> >> <heikki.krogerus@linux.intel.com> wrote:
>>>> >>> >> > Hi,
>>>> >>> >> >
>>>> >>> >> > On Tue, Apr 18, 2017 at 11:52:33AM -0700, Badhri Jagan Sridharan wrote:
>>>> >>> >> >> Hi Heikki,
>>>> >>> >> >>
>>>> >>> >> >> I have a question regarding the preferred_role node.
>>>> >>> >> >>
>>>> >>> >> >> +What:          /sys/class/typec/<port>/preferred_role
>>>> >>> >> >> +Date:          March 2017
>>>> >>> >> >> +Contact:       Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>>> >>> >> >> +Description:
>>>> >>> >> >> +               The user space can notify the driver about the preferred role.
>>>> >>> >> >> +               It should be handled as enabling of Try.SRC or Try.SNK, as
>>>> >>> >> >> +               defined in USB Type-C specification, in the port drivers. By
>>>> >>> >> >> +               default the preferred role should come from the platform.
>>>> >>> >> >> +
>>>> >>> >> >> +               Valid values: source, sink, none (to remove preference)
>>>> >>> >> >>
>>>> >>> >> >> What is the expected behavior when the userspace changes the
>>>> >>> >> >> preferred_role node when the port is in connected state ?
>>>> >>> >> >>
>>>> >>> >> >> 1.  the state machine re-resolves the port roles right away based on
>>>> >>> >> >> the new state machine in place ? (or)
>>>> >>> >> >
>>>> >>> >> > No! There are separate attributes for sending role swap requests.
>>>> >>> >>
>>>> >>> >> Right. But, that might not be helpful in cases when PD is not implemented.
>>>> >>> >> and Implementing PD is not mandatory according the spec :/
>>>> >>> >>
>>>> >>> >> FYI quoting from the Type-C specification release(page 24),
>>>> >>> >> role swaps are not limited to devices that only support PD.
>>>> >>> >>
>>>> >>> >> "Two independent set of mechanisms are defined to allow a USB Type-C
>>>> >>> >> DRP to functionally swap power and data roles. When USB PD is
>>>> >>> >> supported, power and data role swapping is performed as a subsequent
>>>> >>> >> step following the initial connection process. For non-PD implementations,
>>>> >>> >> power/data role swapping can optionally be dealt with as part of the initial
>>>> >>> >> connection process."
>>>> >>> >>
>>>> >>> >> But, the current interface definition actually prevents current/data role
>>>> >>> >> swaps for non-pd devices.
>>>> >>> >>
>>>> >>>
>>>> >>> > This is correct for the attribute definition, but it is not implemented
>>>> >>> > that way. Writing the attribute is only read-only for non-DRP ports.
>>>> >>>
>>>> >>> i.e. tcpm_dr_set/tcpm_pr_set at tcpm.c would return EINVAL when type
>>>> >>> is not TYPEC_PORT_DRP, is that what you are referring to ?
>>>> >>>
>>>> >>>         if (port->typec_caps.type != TYPEC_PORT_DRP) {
>>>> >>>                 ret = -EINVAL;
>>>> >>>                 goto port_unlock;
>>>> >>>         }
>>>> >>>
>>>> >>> I do agree that this is actually correct. I am referring to the case
>>>> >>> where port is
>>>> >>> dual-role-power and dual-role-data but NOT PD capable.
>>>> >>>
>>>> >>> > Given the standard, I would consider that to be intentional; it might
>>>> >>> > make sense to update the description accordingly.
>>>> >>> >
>>>> >>> > How about implementing a mechanism in the dr_set and pr_set code in tcpm
>>>> >>> > which would handle that situation ? Something along the line of
>>>> >>> >
>>>> >>> >         if (!port->pd_capable && connected && current role != desired role) {
>>>> >>> >                 reset_port();
>>>> >>> >                 goto done;
>>>> >>> >         }
>>>> >>>
>>>> >>> By "desired role" you are referring to preferred_role right ?
>>>> >>>
>>>> >>> If so yes, That's a good idea as well and it might work as long as
>>>> >>> type-c connector
>>>> >>> class allows the call to reach tcpm code :) But the current connector
>>>> >>> class code does
>>>> >>> not allow that because the power_role and data_role nodes are defined that way.
>>>> >>
>>>> >> Well, the data_role does not limit the requests from reaching the low
>>>> >> level drivers, but..
>>>> >>
>>>> >>> port->cap->pd_revision and the port->pwr_opmode check in the below code
>>>> >>> stub have to removed/refactored to make current_role/data_role writes to
>>>> >>> reach the tcpm code.
>>>> >>>
>>>> >>> +static ssize_t power_role_store(struct device *dev,
>>>> >>> + struct device_attribute *attr,
>>>> >>> + const char *buf, size_t size)
>>>> >>> +{
>>>> >>> + struct typec_port *port = to_typec_port(dev);
>>>> >>> + int ret = size;
>>>> >>> +
>>>> >>> + if (!port->cap->pd_revision) {
>>>> >>> + dev_dbg(dev, "USB Power Delivery not supported\n");
>>>> >>> + return -EOPNOTSUPP;
>>>> >>> + }
>>>> >>> +
>>>> >>> + if (!port->cap->pr_set) {
>>>> >>> + dev_dbg(dev, "power role swapping not supported\n");
>>>> >>> + return -EOPNOTSUPP;
>>>> >>> + }
>>>> >>> +
>>>> >>> + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) {
>>>> >>> + dev_dbg(dev, "partner unable to swap power role\n");
>>>> >>> + return -EIO;
>>>> >>> + }
>>>> >>> +
>>>> >>> + ret = sysfs_match_string(typec_roles, buf);
>>>> >>> + if (ret < 0)
>>>> >>> + return ret;
>>>> >>> +
>>>> >>> + ret = port->cap->pr_set(port->cap, ret);
>>>> >>> + if (ret)
>>>> >>> + return ret;
>>>> >>> +
>>>> >>> + return size;
>>>> >>> +}
>>>> >>
>>>> >> .. yes. The power_role_store() does indeed need to be refactored. The
>>>> >> PD requirement should only be applied to Type-C spec versions < 1.2,
>>>> >> or removed completely. I would be happy to leave the checks to the low
>>>> >> level drivers.
>>>> >>
>>>> >>
>>>> >> Thanks,
>>>> >>
>>>> >> --
>>>> >> heikki
>>>> > --
>>>> > 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] 64+ messages in thread

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-25  8:26                                             ` Rajaram R
@ 2017-04-25 14:10                                               ` Guenter Roeck
  2017-04-27  6:20                                                 ` Rajaram R
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-04-25 14:10 UTC (permalink / raw)
  To: Rajaram R, Badhri Jagan Sridharan
  Cc: Heikki Krogerus, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

On 04/25/2017 01:26 AM, Rajaram R wrote:
> On Mon, Apr 24, 2017 at 11:20 PM, Badhri Jagan Sridharan
> <badhri@google.com> wrote:
>> On Sat, Apr 22, 2017 at 2:23 AM, Rajaram R <rajaram.officemail@gmail.com> wrote:
>>> On Fri, Apr 21, 2017 at 10:13 PM, Guenter Roeck <linux@roeck-us.net> wrote:
>>>> On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
>>>>> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
>>>>> <badhri@google.com> wrote:
>>>>>> Thanks for the responses :)
>>>>>>
>>>>>> So seems like we have a plan.
>>>>>>
>>>>>> In Type-C connector class the checks for TYPEC_PWR_MODE_PD
>>>>>> and pd_revision for both the port and the partner will be removed in
>>>>>> power_role_store and the data_role_store and will be delegated
>>>>>> to the low level drivers.
>>>>>
>>>>> It is important to remember what USB Type-C provide is mechanisms for
>>>>> "TRYing" to become a particular role and not guaranteeing.
>>>>>
>>>>> With what device combination do you fore see we could get the desired
>>>>> role with this change ?
>>>>>
>>>>
>>>> If the partner is not PD capable, if a preferred role is specified,
>>>> if the current cole does not match the preferred role, and if the request
>>>> is to set the role to match the preferred role, I think it is reasonable
>>>> to expect that re-establishing the connection would accomplish that if the
>>>> partner supports it.
>>>>
>>> In this context I believe we have two different inputs as follows:
>>>
>>> /sys/class/typec/<port>/supported_power_roles
>>> /sys/class/typec/<port>/preferred_role
>>>
>>> The need of preferred role is required when DRP is set in
>>> supported_power_roles option.
>>> Ideally a battery powered device will TRY to be SNK and a a/c plugged
>>> device will TRY to be SRC
>>>
>>> We need to understand which non-PD device will set to DRP? In the
>>
>> Android Phones (actually it could be any phone which has a type-c port)
>> since it can act as usb gadget (when connected to PC) or Usb host
>> when connected to peripherals such as thumb drives, keyboard etc.
>> Phones with smaller form factors might be thermally limited to charge
>> above 15W, therefore supporting PD might be an overkill for them.
>>
>>> current ecosystem all legacy devices
>>> will sit behind adapters which either present an Rp or Rd.
>>>
>>> If it is a power adapter in 5V range can either present Rp or DRP with
>>> TRY.SRC and there is no role swap requirement.
>>>
>>> If it is a laptop port or similar with non-PD (??) DRP  there is no
>>> guaranteed role swap in a non-PD mode.
>>
>> This is true, but following a Try.SRC or Try.SNK state machine can
>> increase the chances of landing in the desired role/preferred role.
>
> Agree and as indicated it increases only chances.
>

FWIW, this is pretty much the same as requesting a role change using PD.
Based on my experience with various devices, the chance for that to succeed
isn't really that high either.

I am not really sure I understand your problem with using Try.{SRC,SNK}
to trigger (or attempt to trigger) a role change. Can we take a step back,
and can you explain ?

Thanks,
Guenter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-25 14:10                                               ` Guenter Roeck
@ 2017-04-27  6:20                                                 ` Rajaram R
  2017-04-27 18:10                                                   ` Guenter Roeck
  0 siblings, 1 reply; 64+ messages in thread
From: Rajaram R @ 2017-04-27  6:20 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Badhri Jagan Sridharan, Heikki Krogerus, Oliver Neukum,
	Mats Karrman, Greg KH, Felipe Balbi, LKML, USB

On Tue, Apr 25, 2017 at 7:40 PM, Guenter Roeck <linux@roeck-us.net> wrote:
> On 04/25/2017 01:26 AM, Rajaram R wrote:
>>
>> On Mon, Apr 24, 2017 at 11:20 PM, Badhri Jagan Sridharan
>> <badhri@google.com> wrote:
>>>
>>> On Sat, Apr 22, 2017 at 2:23 AM, Rajaram R <rajaram.officemail@gmail.com>
>>> wrote:
>>>>
>>>> On Fri, Apr 21, 2017 at 10:13 PM, Guenter Roeck <linux@roeck-us.net>
>>>> wrote:
>>>>>
>>>>> On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
>>>>>>
>>>>>> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
>>>>>> <badhri@google.com> wrote:
>>>>>>>
>>>>>>> Thanks for the responses :)
>>>>>>>
>>>>>>> So seems like we have a plan.
>>>>>>>
>>>>>>> In Type-C connector class the checks for TYPEC_PWR_MODE_PD
>>>>>>> and pd_revision for both the port and the partner will be removed in
>>>>>>> power_role_store and the data_role_store and will be delegated
>>>>>>> to the low level drivers.
>>>>>>
>>>>>>
>>>>>> It is important to remember what USB Type-C provide is mechanisms for
>>>>>> "TRYing" to become a particular role and not guaranteeing.
>>>>>>
>>>>>> With what device combination do you fore see we could get the desired
>>>>>> role with this change ?
>>>>>>
>>>>>
>>>>> If the partner is not PD capable, if a preferred role is specified,
>>>>> if the current cole does not match the preferred role, and if the
>>>>> request
>>>>> is to set the role to match the preferred role, I think it is
>>>>> reasonable
>>>>> to expect that re-establishing the connection would accomplish that if
>>>>> the
>>>>> partner supports it.
>>>>>
>>>> In this context I believe we have two different inputs as follows:
>>>>
>>>> /sys/class/typec/<port>/supported_power_roles
>>>> /sys/class/typec/<port>/preferred_role
>>>>
>>>> The need of preferred role is required when DRP is set in
>>>> supported_power_roles option.
>>>> Ideally a battery powered device will TRY to be SNK and a a/c plugged
>>>> device will TRY to be SRC
>>>>
>>>> We need to understand which non-PD device will set to DRP? In the
>>>
>>>
>>> Android Phones (actually it could be any phone which has a type-c port)
>>> since it can act as usb gadget (when connected to PC) or Usb host
>>> when connected to peripherals such as thumb drives, keyboard etc.
>>> Phones with smaller form factors might be thermally limited to charge
>>> above 15W, therefore supporting PD might be an overkill for them.
>>>
>>>> current ecosystem all legacy devices
>>>> will sit behind adapters which either present an Rp or Rd.
>>>>
>>>> If it is a power adapter in 5V range can either present Rp or DRP with
>>>> TRY.SRC and there is no role swap requirement.
>>>>
>>>> If it is a laptop port or similar with non-PD (??) DRP  there is no
>>>> guaranteed role swap in a non-PD mode.
>>>
>>>
>>> This is true, but following a Try.SRC or Try.SNK state machine can
>>> increase the chances of landing in the desired role/preferred role.
>>
>>
>> Agree and as indicated it increases only chances.
>>
>
> FWIW, this is pretty much the same as requesting a role change using PD.
> Based on my experience with various devices, the chance for that to succeed
> isn't really that high either.
>
> I am not really sure I understand your problem with using Try.{SRC,SNK}
> to trigger (or attempt to trigger) a role change. Can we take a step back,
> and can you explain ?

The parameters required for a type-c connection is defined as follows
and will have a default value.

/sys/class/typec/<port>/supported_power_roles
/sys/class/typec/<port>/preferred_role

When two DRP devices are connected and for which we have
preferred_role which provides input on the preference, In a DRP mode
we have randomness in the mode of connection and hence we require role
swap mechanisms. A Type-C only device cannot role swap as this is
valid only in PD operation.

#  Question was how to choose a particular role in non-PD mode. Only
way to have a deterministic role in a non-PD mode is to set expected
supported_role of choice rather than DRP.

# As part of the solution suggested, checking of roles and triggering
role swaps has to be done by the policy manager(PM) and delinked from
Policy Engine. I guess the policy manager is at user space?.

I do not have the complete git repo and may be i could be missing
something. If this is in any public git please let me know

>
> Thanks,
> Guenter
>

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-27  6:20                                                 ` Rajaram R
@ 2017-04-27 18:10                                                   ` Guenter Roeck
  2017-04-28 10:52                                                     ` Heikki Krogerus
  0 siblings, 1 reply; 64+ messages in thread
From: Guenter Roeck @ 2017-04-27 18:10 UTC (permalink / raw)
  To: Rajaram R
  Cc: Badhri Jagan Sridharan, Heikki Krogerus, Oliver Neukum,
	Mats Karrman, Greg KH, Felipe Balbi, LKML, USB

On Thu, Apr 27, 2017 at 11:50:12AM +0530, Rajaram R wrote:
> On Tue, Apr 25, 2017 at 7:40 PM, Guenter Roeck <linux@roeck-us.net> wrote:
> > On 04/25/2017 01:26 AM, Rajaram R wrote:
> >>
> >> On Mon, Apr 24, 2017 at 11:20 PM, Badhri Jagan Sridharan
> >> <badhri@google.com> wrote:
> >>>
> >>> On Sat, Apr 22, 2017 at 2:23 AM, Rajaram R <rajaram.officemail@gmail.com>
> >>> wrote:
> >>>>
> >>>> On Fri, Apr 21, 2017 at 10:13 PM, Guenter Roeck <linux@roeck-us.net>
> >>>> wrote:
> >>>>>
> >>>>> On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
> >>>>>>
> >>>>>> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
> >>>>>> <badhri@google.com> wrote:
> >>>>>>>
> >>>>>>> Thanks for the responses :)
> >>>>>>>
> >>>>>>> So seems like we have a plan.
> >>>>>>>
> >>>>>>> In Type-C connector class the checks for TYPEC_PWR_MODE_PD
> >>>>>>> and pd_revision for both the port and the partner will be removed in
> >>>>>>> power_role_store and the data_role_store and will be delegated
> >>>>>>> to the low level drivers.
> >>>>>>
> >>>>>>
> >>>>>> It is important to remember what USB Type-C provide is mechanisms for
> >>>>>> "TRYing" to become a particular role and not guaranteeing.
> >>>>>>
> >>>>>> With what device combination do you fore see we could get the desired
> >>>>>> role with this change ?
> >>>>>>
> >>>>>
> >>>>> If the partner is not PD capable, if a preferred role is specified,
> >>>>> if the current cole does not match the preferred role, and if the
> >>>>> request
> >>>>> is to set the role to match the preferred role, I think it is
> >>>>> reasonable
> >>>>> to expect that re-establishing the connection would accomplish that if
> >>>>> the
> >>>>> partner supports it.
> >>>>>
> >>>> In this context I believe we have two different inputs as follows:
> >>>>
> >>>> /sys/class/typec/<port>/supported_power_roles
> >>>> /sys/class/typec/<port>/preferred_role
> >>>>
> >>>> The need of preferred role is required when DRP is set in
> >>>> supported_power_roles option.
> >>>> Ideally a battery powered device will TRY to be SNK and a a/c plugged
> >>>> device will TRY to be SRC
> >>>>
> >>>> We need to understand which non-PD device will set to DRP? In the
> >>>
> >>>
> >>> Android Phones (actually it could be any phone which has a type-c port)
> >>> since it can act as usb gadget (when connected to PC) or Usb host
> >>> when connected to peripherals such as thumb drives, keyboard etc.
> >>> Phones with smaller form factors might be thermally limited to charge
> >>> above 15W, therefore supporting PD might be an overkill for them.
> >>>
> >>>> current ecosystem all legacy devices
> >>>> will sit behind adapters which either present an Rp or Rd.
> >>>>
> >>>> If it is a power adapter in 5V range can either present Rp or DRP with
> >>>> TRY.SRC and there is no role swap requirement.
> >>>>
> >>>> If it is a laptop port or similar with non-PD (??) DRP  there is no
> >>>> guaranteed role swap in a non-PD mode.
> >>>
> >>>
> >>> This is true, but following a Try.SRC or Try.SNK state machine can
> >>> increase the chances of landing in the desired role/preferred role.
> >>
> >>
> >> Agree and as indicated it increases only chances.
> >>
> >
> > FWIW, this is pretty much the same as requesting a role change using PD.
> > Based on my experience with various devices, the chance for that to succeed
> > isn't really that high either.
> >
> > I am not really sure I understand your problem with using Try.{SRC,SNK}
> > to trigger (or attempt to trigger) a role change. Can we take a step back,
> > and can you explain ?
> 
> The parameters required for a type-c connection is defined as follows
> and will have a default value.
> 
> /sys/class/typec/<port>/supported_power_roles

I don't see that attribute (it is implied in the power_role attribute).
It only existed in an earlier version of the driver.

Also, the attribute (when it existed) listed the roles supported
by the port, not an administrative restriction of supported roles.

> /sys/class/typec/<port>/preferred_role
> 
> When two DRP devices are connected and for which we have
> preferred_role which provides input on the preference, In a DRP mode
> we have randomness in the mode of connection and hence we require role
> swap mechanisms. A Type-C only device cannot role swap as this is
> valid only in PD operation.
> 

The same is true for non-PD connections. Also, PD doesn't solve the problem
if both ends have the same source/sink preference. The result is still
randomness. To resolve that randomness, one of the connection partners
would have to give up its preference. That is quite independent of PD
support.

> #  Question was how to choose a particular role in non-PD mode. Only
> way to have a deterministic role in a non-PD mode is to set expected
> supported_role of choice rather than DRP.
> 
> # As part of the solution suggested, checking of roles and triggering
> role swaps has to be done by the policy manager(PM) and delinked from
> Policy Engine. I guess the policy manager is at user space?.
> 
> I do not have the complete git repo and may be i could be missing
> something. If this is in any public git please let me know
> 

Even if a device does support PD, there is no guarantee that a power role
swap is successful. That depends on the policy set by the partner, and
for all practical purposes it also depends on the quality and stability
of the PD protocol implementation on both ends. As mentioned above, if
both ends have the same preferred role, the result is still randomness
and requires manual intervention by the user if the "other" role is
desired.

It seems to me that we are discussing if we should do as good as we can
or if we should only implement what can be guaranteed. I strongly favor
the first approach. I also think we should not preclude that approach in
the kernel implementation. It should be left to a specific policy manager
implementation to decide if a given device should be a DRP or source-only
or sink-only, independent of the question if PD is supported on either
end of a connection.

If a given implementation wants to restrict available port modes, it
can do so by providing acceptable port capabilities (ie DRP or source
or sink) when registering the port with the infrastructure.

I think you are suggesting that there should be a means to override port
capabilities (more specifically, permitted roles) after port registration.
That may be a matter for discussion, but it is a separate issue.
Also, I am not sure if it was already discussed. Does anyone remember ?

Thanks,
Guenter

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

* Re: [PATCH v17 2/3] usb: USB Type-C connector class
  2017-04-27 18:10                                                   ` Guenter Roeck
@ 2017-04-28 10:52                                                     ` Heikki Krogerus
  0 siblings, 0 replies; 64+ messages in thread
From: Heikki Krogerus @ 2017-04-28 10:52 UTC (permalink / raw)
  To: Guenter Roeck, Rajaram R
  Cc: Badhri Jagan Sridharan, Oliver Neukum, Mats Karrman, Greg KH,
	Felipe Balbi, LKML, USB

On Thu, Apr 27, 2017 at 11:10:55AM -0700, Guenter Roeck wrote:
> On Thu, Apr 27, 2017 at 11:50:12AM +0530, Rajaram R wrote:
> > On Tue, Apr 25, 2017 at 7:40 PM, Guenter Roeck <linux@roeck-us.net> wrote:
> > > On 04/25/2017 01:26 AM, Rajaram R wrote:
> > >>
> > >> On Mon, Apr 24, 2017 at 11:20 PM, Badhri Jagan Sridharan
> > >> <badhri@google.com> wrote:
> > >>>
> > >>> On Sat, Apr 22, 2017 at 2:23 AM, Rajaram R <rajaram.officemail@gmail.com>
> > >>> wrote:
> > >>>>
> > >>>> On Fri, Apr 21, 2017 at 10:13 PM, Guenter Roeck <linux@roeck-us.net>
> > >>>> wrote:
> > >>>>>
> > >>>>> On Fri, Apr 21, 2017 at 07:57:52PM +0530, Rajaram R wrote:
> > >>>>>>
> > >>>>>> On Fri, Apr 21, 2017 at 1:16 AM, Badhri Jagan Sridharan
> > >>>>>> <badhri@google.com> wrote:
> > >>>>>>>
> > >>>>>>> Thanks for the responses :)
> > >>>>>>>
> > >>>>>>> So seems like we have a plan.
> > >>>>>>>
> > >>>>>>> In Type-C connector class the checks for TYPEC_PWR_MODE_PD
> > >>>>>>> and pd_revision for both the port and the partner will be removed in
> > >>>>>>> power_role_store and the data_role_store and will be delegated
> > >>>>>>> to the low level drivers.
> > >>>>>>
> > >>>>>>
> > >>>>>> It is important to remember what USB Type-C provide is mechanisms for
> > >>>>>> "TRYing" to become a particular role and not guaranteeing.
> > >>>>>>
> > >>>>>> With what device combination do you fore see we could get the desired
> > >>>>>> role with this change ?
> > >>>>>>
> > >>>>>
> > >>>>> If the partner is not PD capable, if a preferred role is specified,
> > >>>>> if the current cole does not match the preferred role, and if the
> > >>>>> request
> > >>>>> is to set the role to match the preferred role, I think it is
> > >>>>> reasonable
> > >>>>> to expect that re-establishing the connection would accomplish that if
> > >>>>> the
> > >>>>> partner supports it.
> > >>>>>
> > >>>> In this context I believe we have two different inputs as follows:
> > >>>>
> > >>>> /sys/class/typec/<port>/supported_power_roles
> > >>>> /sys/class/typec/<port>/preferred_role
> > >>>>
> > >>>> The need of preferred role is required when DRP is set in
> > >>>> supported_power_roles option.
> > >>>> Ideally a battery powered device will TRY to be SNK and a a/c plugged
> > >>>> device will TRY to be SRC
> > >>>>
> > >>>> We need to understand which non-PD device will set to DRP? In the
> > >>>
> > >>>
> > >>> Android Phones (actually it could be any phone which has a type-c port)
> > >>> since it can act as usb gadget (when connected to PC) or Usb host
> > >>> when connected to peripherals such as thumb drives, keyboard etc.
> > >>> Phones with smaller form factors might be thermally limited to charge
> > >>> above 15W, therefore supporting PD might be an overkill for them.
> > >>>
> > >>>> current ecosystem all legacy devices
> > >>>> will sit behind adapters which either present an Rp or Rd.
> > >>>>
> > >>>> If it is a power adapter in 5V range can either present Rp or DRP with
> > >>>> TRY.SRC and there is no role swap requirement.
> > >>>>
> > >>>> If it is a laptop port or similar with non-PD (??) DRP  there is no
> > >>>> guaranteed role swap in a non-PD mode.
> > >>>
> > >>>
> > >>> This is true, but following a Try.SRC or Try.SNK state machine can
> > >>> increase the chances of landing in the desired role/preferred role.
> > >>
> > >>
> > >> Agree and as indicated it increases only chances.
> > >>
> > >
> > > FWIW, this is pretty much the same as requesting a role change using PD.
> > > Based on my experience with various devices, the chance for that to succeed
> > > isn't really that high either.
> > >
> > > I am not really sure I understand your problem with using Try.{SRC,SNK}
> > > to trigger (or attempt to trigger) a role change. Can we take a step back,
> > > and can you explain ?
> > 
> > The parameters required for a type-c connection is defined as follows
> > and will have a default value.
> > 
> > /sys/class/typec/<port>/supported_power_roles
> 
> I don't see that attribute (it is implied in the power_role attribute).
> It only existed in an earlier version of the driver.
> 
> Also, the attribute (when it existed) listed the roles supported
> by the port, not an administrative restriction of supported roles.
> 
> > /sys/class/typec/<port>/preferred_role
> > 
> > When two DRP devices are connected and for which we have
> > preferred_role which provides input on the preference, In a DRP mode
> > we have randomness in the mode of connection and hence we require role
> > swap mechanisms. A Type-C only device cannot role swap as this is
> > valid only in PD operation.
> > 
> 
> The same is true for non-PD connections. Also, PD doesn't solve the problem
> if both ends have the same source/sink preference. The result is still
> randomness. To resolve that randomness, one of the connection partners
> would have to give up its preference. That is quite independent of PD
> support.
> 
> > #  Question was how to choose a particular role in non-PD mode. Only
> > way to have a deterministic role in a non-PD mode is to set expected
> > supported_role of choice rather than DRP.
> > 
> > # As part of the solution suggested, checking of roles and triggering
> > role swaps has to be done by the policy manager(PM) and delinked from
> > Policy Engine. I guess the policy manager is at user space?.
> > 
> > I do not have the complete git repo and may be i could be missing
> > something. If this is in any public git please let me know
> > 
> 
> Even if a device does support PD, there is no guarantee that a power role
> swap is successful. That depends on the policy set by the partner, and
> for all practical purposes it also depends on the quality and stability
> of the PD protocol implementation on both ends. As mentioned above, if
> both ends have the same preferred role, the result is still randomness
> and requires manual intervention by the user if the "other" role is
> desired.
> 
> It seems to me that we are discussing if we should do as good as we can
> or if we should only implement what can be guaranteed. I strongly favor
> the first approach. I also think we should not preclude that approach in
> the kernel implementation. It should be left to a specific policy manager
> implementation to decide if a given device should be a DRP or source-only
> or sink-only, independent of the question if PD is supported on either
> end of a connection.
> 
> If a given implementation wants to restrict available port modes, it
> can do so by providing acceptable port capabilities (ie DRP or source
> or sink) when registering the port with the infrastructure.
> 
> I think you are suggesting that there should be a means to override port
> capabilities (more specifically, permitted roles) after port registration.
> That may be a matter for discussion, but it is a separate issue.

That is how also I see it.

> Also, I am not sure if it was already discussed. Does anyone remember ?

Yes, I did propose an attribute that would allow fixing the role of a
port to either sink or source at one point. I don't remember what was
the reason I ended up dropping that proposal - I need to go through my
archives - but I think it was seen as a feature that, if needed, can be
added later by adding a new attribute file for it.

So if that is the functionality you want, please start a new thread
and propose the new attribute. At least don't try to modify the
behaviour of the existing ones because of it.


Thank you,

-- 
heikki

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

end of thread, other threads:[~2017-04-28 10:52 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-21 14:24 [PATCH v17 0/3] USB Type-C Connector class Heikki Krogerus
2017-02-21 14:24 ` [PATCH v17 1/3] lib/string: add sysfs_match_string helper Heikki Krogerus
2017-02-21 14:24 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
2017-03-02 15:22   ` Mats Karrman
2017-03-03  3:13     ` Guenter Roeck
2017-03-03  7:29       ` Mats Karrman
2017-03-03  9:48         ` Enric Balletbo Serra
2017-03-03 12:59         ` Heikki Krogerus
2017-03-03 14:49           ` Guenter Roeck
2017-03-03 19:27           ` Mats Karrman
2017-03-06  9:37             ` Oliver Neukum
2017-03-06 13:14             ` Heikki Krogerus
2017-03-07 22:30               ` Mats Karrman
2017-03-08  1:38                 ` Guenter Roeck
2017-04-08 23:09                   ` USB Type-C Port Manager API concern Mats Karrman
2017-04-09 15:16                     ` Guenter Roeck
2017-04-09 21:05                       ` Mats Karrman
2017-04-14  2:57                         ` Guenter Roeck
2017-04-14  8:30                           ` Mats Karrman
2017-03-08 13:58                 ` [PATCH v17 2/3] usb: USB Type-C connector class Heikki Krogerus
2017-03-10 22:22                   ` Mats Karrman
2017-03-10 23:41                     ` Guenter Roeck
2017-04-18 18:52                       ` Badhri Jagan Sridharan
2017-04-19 11:23                         ` Heikki Krogerus
2017-04-19 14:45                           ` Badhri Jagan Sridharan
2017-04-19 15:14                             ` Guenter Roeck
2017-04-19 17:22                               ` Badhri Jagan Sridharan
2017-04-19 19:29                                 ` Guenter Roeck
2017-04-20 12:24                                 ` Heikki Krogerus
2017-04-20 19:46                                   ` Badhri Jagan Sridharan
2017-04-21 12:12                                     ` Heikki Krogerus
2017-04-21 13:14                                       ` Guenter Roeck
2017-04-21 14:27                                     ` Rajaram R
2017-04-21 16:43                                       ` Guenter Roeck
2017-04-22  9:23                                         ` Rajaram R
2017-04-24 17:50                                           ` Badhri Jagan Sridharan
2017-04-25  8:26                                             ` Rajaram R
2017-04-25 14:10                                               ` Guenter Roeck
2017-04-27  6:20                                                 ` Rajaram R
2017-04-27 18:10                                                   ` Guenter Roeck
2017-04-28 10:52                                                     ` Heikki Krogerus
2017-04-20 11:55                             ` Heikki Krogerus
2017-03-03 14:41         ` Guenter Roeck
2017-03-03  3:35   ` Peter Chen
2017-03-03  4:29     ` Guenter Roeck
2017-03-03  4:52       ` Peter Chen
2017-03-03 14:36         ` Guenter Roeck
2017-03-06  1:24           ` Peter Chen
2017-03-03 14:31     ` Heikki Krogerus
2017-03-06  1:15       ` Peter Chen
2017-03-06 13:16         ` Heikki Krogerus
2017-03-07  1:36           ` Peter Chen
2017-03-07  8:57             ` Heikki Krogerus
2017-03-08  1:53               ` Guenter Roeck
2017-03-08  6:50                 ` Peter Chen
2017-03-08 14:44                   ` Guenter Roeck
2017-03-09  2:00                     ` Peter Chen
2017-02-21 14:24 ` [PATCH v17 3/3] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY Heikki Krogerus
2017-02-21 15:42 ` [PATCH v17 0/3] USB Type-C Connector class Felipe Balbi
2017-03-21 11:14   ` Heikki Krogerus
2017-03-21 10:23 ` Greg KH
2017-03-21 10:37   ` Heikki Krogerus
2017-03-22 21:15     ` Mats Karrman
2017-03-23  8:16       ` Heikki Krogerus

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).