* [PATCHv3 0/2] USB Type-C Connector class @ 2016-06-21 14:51 Heikki Krogerus 2016-06-21 14:51 ` [PATCHv3 1/2] usb: USB Type-C connector class Heikki Krogerus ` (2 more replies) 0 siblings, 3 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-21 14:51 UTC (permalink / raw) To: Greg KH, Guenter Roeck, Oliver Neukum Cc: Felipe Balbi, linux-kernel, linux-usb Hi, I'm considering all the RFCs I send after v1 as v2 (I don't remember how many I send). Hope this is OK and hope there is nothing big missing anymore (or broken). Sorry about the delay. I've been really busy with some internal tasks. I'm guessing we missed v4.8 with this thing. I'm sorry about that. I'm including in this series a driver for the Broxton PMIC USB Type-C PHY. 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 (2): 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 | 163 ++++ Documentation/usb/typec.txt | 101 +++ MAINTAINERS | 9 + drivers/usb/Kconfig | 2 + drivers/usb/Makefile | 2 + drivers/usb/typec/Kconfig | 21 + drivers/usb/typec/Makefile | 2 + drivers/usb/typec/typec.c | 1173 +++++++++++++++++++++++++++ drivers/usb/typec/typec_wcove.c | 376 +++++++++ include/linux/usb/typec.h | 255 ++++++ 10 files changed, 2104 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-typec create mode 100644 Documentation/usb/typec.txt 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.8.1 ^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-21 14:51 [PATCHv3 0/2] USB Type-C Connector class Heikki Krogerus @ 2016-06-21 14:51 ` Heikki Krogerus 2016-06-21 20:25 ` Oliver Neukum ` (3 more replies) 2016-06-21 14:51 ` [PATCHv3 2/2] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY Heikki Krogerus 2016-06-21 22:25 ` [PATCHv3 0/2] USB Type-C Connector class Guenter Roeck 2 siblings, 4 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-21 14:51 UTC (permalink / raw) To: Greg KH, Guenter Roeck, Oliver Neukum Cc: Felipe Balbi, 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 USB PD is available, also control over power role swapping and Alternate Modes. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> --- Documentation/ABI/testing/sysfs-class-typec | 163 ++++ Documentation/usb/typec.txt | 101 +++ 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 | 1173 +++++++++++++++++++++++++++ include/linux/usb/typec.h | 255 ++++++ 9 files changed, 1713 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-typec create mode 100644 Documentation/usb/typec.txt 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 0000000..ce577f3 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-typec @@ -0,0 +1,163 @@ +USB Type-C port devices (eg. /sys/class/typec/usbc0/) + +What: /sys/class/typec/<port>/current_data_role +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + The current USB data role the port is operating in. This + attribute can be used for requestion data role swapping on th + port. + +What: /sys/class/typec/<port>/current_power_role +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + The current power role, source or sink, of the port. This + attribute can be used to request power role swap on the port + when USB Power Delivery is available. + +What: /sys/class/typec/<port>/current_vconn_role +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows the current VCONN role, source or sink, of the port. This + attribute can be used to request vconn role swap on the port + when USB Power Delivery is available. + +What: /sys/class/typec/<port>/power_operation_mode +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows the current power power mode the port is in. Reads as on + of the following: + - USB - Normal power levels defined in USB specifications + - BC1.2 - Power levels defined in Battery Charging Specification + v1.2 + - USB Type-C 1.5A - Higher 1.5A current defined in USB Type-C + specification. + - USB Type-C 3.0A - Higher 3A current defined in USB Type-C + specification. + - USB Power Delivery - The voltages and currents defined in USB + Power Delivery specification + +What: /sys/class/typec/<port>/preferred_role +Data: June 2016 +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. + +What: /sys/class/typec/<port>/supported_accessory_modes +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Lists the Accessory Modes, defined in the USB Type-C + specification, the port supports. + +What: /sys/class/typec/<port>/supported_data_roles +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Lists the USB data roles, host or device, the port is capable + of supporting. + +What: /sys/class/typec/<port>/supported_power_roles +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Lists the power roles, source and/or sink, the port is capable + of supporting. + +What: /sys/class/typec/<port>/supports_usb_power_delivery +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows if the port support USB Power Delivery. + + +USB Type-C partner devices (eg. /sys/class/typec/usbc0-partner/) + +What: /sys/class/typec/<port>-partner/accessory +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows the name of the Accessory Mode if the partner attached to + the port is an accessory. Otherwise shows nothing. + +What: /sys/class/typec/<port>-partner/type +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows the type of the partner. Can be one of the following: + - USB - When the partner is normal USB host/peripheral. + - Charger - When the partner has been identified as dedicated + charger. + - Alternate Mode - When the partner supports Alternate Modes. + - Accessory - When the partner is one of the accessories with + specific Accessory Mode defined in USB Type-C + specification. + + +USB Type-C cable devices (eg. /sys/class/typec/usbc0-cable/) + +Note: The two cable plugs will have their own devices presenting when available +(eg. /sys/class/typec/usbc0-plug0). Both plugs may have their own active +alternate modes as described in USB Type-C and USB Power Delivery +specifications. + +What: /sys/class/typec/<port>-cable/active +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows if the cable is active or passive. Only active cables can + have configurable alternate modes, therefore only active cables + will have plug devices. + +What: /sys/class/typec/<port>-cable/plug_type +Data: June 2016 +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 - USB Type-C + Captive - Non-standard + + +Alternate Mode devices (For example, +/sys/class/typec/usbc0-partner/usbc0-partner.svid:xxxx/) + +What: /sys/class/typec/<dev>/<dev>.svid:<svid>/<mode>/active +Data: June 2016 +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. + +What: /sys/class/typec/<dev>/<dev>.svid:<svid>/<mode>/description +Data: June 2016 +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/<dev>/<dev>.svid:<svid>/<mode>/vdo +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows the VDO in hexadecimal returned from the Discover Modes + command. + +What: /sys/class/typec/<port>/<port>.svid:<svid>/<mode>/supported_roles +Data: June 2016 +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Description: + Shows the roles, source or sink, the mode is supported with. + + 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. diff --git a/Documentation/usb/typec.txt b/Documentation/usb/typec.txt new file mode 100644 index 0000000..ddeda97 --- /dev/null +++ b/Documentation/usb/typec.txt @@ -0,0 +1,101 @@ +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 +expect 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 offers the user space control +over the roles and alternate modes they support 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. + + +Interface +--------- +Every port will be presented as its own device under /sys/class/typec/. The +first port will be named "usbc0", the second "usbc1" 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. The +partner attached to port "usbc0" will be named "usbc0-partner". + +The cable and the two plugs on it may also be optionally be presented as their +own devices under /sys/class/typec/. The cable attached to the port "usbc0" port +will be named usbc0-cable and the plug on the SOP Prime end (see USB Power +Delivery Specification ch. 2.4) will be named "usbc-plug0" and on the SOP Double +Prime end "usbc0-plug1". + +If the port, partner or cable plug support Alternate Modes, every Alternate Mode +SVID will have their own device describing them. The Alternate Modes will not be +attached to the typec class. For the port's "usbc0" partner, the Alternate Modes +would have devices presented under /sys/class/typec/usbc0-partner/. Every mode +that is supported will have its own group under the Alternate Mode device named +"mode<id>". For example /sys/class/typec/usbc0/usbc0.svid:xxxx/mode0/. The +requests for entering/exiting the modes happens with the "active" attribute in +that group. + + +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: + +struct typec_port *typec_register_port(struct device *dev, + const struct typec_capability *cap); + +The class will provide handle to struct typec_port on success and ERR_PTR on +failure. The un-registration of the port happens with the following API: + +void typec_unregister_port(struct typec_port *port); + + +* Notifications + +When connection happens on a port, the port driver fills struct typec_connection +which is passed to the class. The class provides the following API for reporting +connection/disconnection: + +int typec_connect(struct typec_port *port, struct typec_connection *); +void typec_disconnect(struct typec_port *); + +When the partner end has executed a role change, the port driver uses the +following APIs to report it to the class: + +void typec_set_data_role(struct typec_port *, enum typec_data_role); +void typec_set_pwr_role(struct typec_port *, enum typec_role); +void typec_set_vconn_role(struct typec_port *, enum typec_role); +void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode); + + +* Alternate Modes + +After connection, the port drivers register the alternate modes the partner +and/or cable plugs support. And before reporting disconnection, the port driver +_must_ unregister all the alternate modes registered for the partner and cable +plugs. The API takes the struct device of the partner or the cable plug as +parameter: + +int typec_register_altmodes(struct device *, struct typec_altmode *); +void typec_unregister_altmodes(struct device *); + +When the partner end enters or exits the modes, the port driver needs to notify +the class with the following API: + +void typec_altmode_update_active(struct typec_altmode *alt, int mode, + bool active); diff --git a/MAINTAINERS b/MAINTAINERS index e1b090f..0db33fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11983,6 +11983,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.txt +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 8689dcb..f42a3d3 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -150,6 +150,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 && USB_COMMON && LEDS_TRIGGERS diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index dca7856..51e381e 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -61,3 +61,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 0000000..b229fb9 --- /dev/null +++ b/drivers/usb/typec/Kconfig @@ -0,0 +1,7 @@ + +menu "USB PD 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 0000000..1012a8b --- /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 0000000..c6363bf --- /dev/null +++ b/drivers/usb/typec/typec.c @@ -0,0 +1,1173 @@ +/* + * USB Type-C Connector Class + * + * Copyright (C) 2016, 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_port { + unsigned int id; + struct device dev; + struct mutex lock; /* device lock */ + + 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; + + struct typec_partner *partner; + struct typec_cable *cable; + + unsigned int connected:1; + + const struct typec_capability *cap; +}; + +#define to_typec_port(p) container_of(p, struct typec_port, dev) + +static DEFINE_IDA(typec_index_ida); + +static struct class typec_class = { + .name = "typec", +}; + +static const char * const typec_accessory_modes[] = { + [TYPEC_ACCESSORY_NONE] = "none", + [TYPEC_ACCESSORY_AUDIO] = "Audio", + [TYPEC_ACCESSORY_DEBUG] = "Debug", + [TYPEC_ACCESSORY_DAUDIO] = "Digital Audio", +}; + +/* -------------------------------- */ +/* Type-C Partners */ + +static void typec_dev_release(struct device *dev) +{ +} + +static const char * const typec_partner_types[] = { + [TYPEC_PARTNER_USB] = "USB", + [TYPEC_PARTNER_CHARGER] = "Charger", + [TYPEC_PARTNER_ALTMODE] = "Alternate Mode", + [TYPEC_PARTNER_ACCESSORY] = "Accessory", +}; + +static ssize_t partner_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct typec_partner *partner = container_of(dev, struct typec_partner, + dev); + + return sprintf(buf, "%s\n", typec_partner_types[partner->type]); +} + +static struct device_attribute dev_attr_partner_type = { + .attr = { + .name = "type", + .mode = S_IRUGO, + }, + .show = partner_type_show, +}; + +static ssize_t +partner_accessory_mode_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct typec_partner *partner = container_of(dev, struct typec_partner, + dev); + + return sprintf(buf, "%s\n", typec_accessory_modes[partner->accessory]); +} + +static struct device_attribute dev_attr_partner_accessory = { + .attr = { + .name = "accessory", + .mode = S_IRUGO, + }, + .show = partner_accessory_mode_show, +}; + +static struct attribute *typec_partner_attrs[] = { + &dev_attr_partner_type.attr, + &dev_attr_partner_accessory.attr, + NULL +}; + +static struct attribute_group typec_partner_group = { + .attrs = typec_partner_attrs, +}; + +static const struct attribute_group *typec_partner_groups[] = { + &typec_partner_group, + NULL +}; + +static struct device_type typec_partner_dev_type = { + .name = "typec_partner_device", + .groups = typec_partner_groups, + .release = typec_dev_release, +}; + +static int +typec_add_partner(struct typec_port *port, struct typec_partner *partner) +{ + struct device *dev = &partner->dev; + int ret; + + dev->class = &typec_class; + dev->parent = &port->dev; + dev->type = &typec_partner_dev_type; + dev_set_name(dev, "%s-partner", dev_name(&port->dev)); + + ret = device_register(dev); + if (ret) { + put_device(dev); + return ret; + } + + port->partner = partner; + return 0; +} + +static void typec_remove_partner(struct typec_port *port) +{ + WARN_ON(port->partner->alt_modes); + device_unregister(&port->partner->dev); +} + +/* ------------------------------------------------------------------------- */ +/* Type-C Cable Plugs */ + +static struct device_type typec_plug_dev_type = { + .name = "type_plug_device", + .release = typec_dev_release, +}; + +static int +typec_add_plug(struct typec_port *port, struct typec_plug *plug) +{ + struct device *dev = &plug->dev; + char name[8]; + int ret; + + sprintf(name, "plug%d", plug->index); + + dev->class = &typec_class; + dev->parent = &port->cable->dev; + dev->type = &typec_plug_dev_type; + dev_set_name(dev, "%s-%s", dev_name(&port->dev), name); + + ret = device_register(dev); + if (ret) { + put_device(dev); + return ret; + } + + return 0; +} + +static void typec_remove_plug(struct typec_plug *plug) +{ + WARN_ON(plug->alt_modes); + device_unregister(&plug->dev); +} + +static ssize_t +active_cable_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct typec_cable *cable = container_of(dev, struct typec_cable, dev); + + return sprintf(buf, "%d\n", cable->active); +} + +static struct device_attribute dev_attr_active_cable = { + .attr = { + .name = "active", + .mode = S_IRUGO, + }, + .show = active_cable_show, +}; + +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 +cable_plug_type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct typec_cable *cable = container_of(dev, struct typec_cable, dev); + + return sprintf(buf, "%s\n", typec_plug_types[cable->type]); +} + +static struct device_attribute dev_attr_plug_type = { + .attr = { + .name = "plug_type", + .mode = S_IRUGO, + }, + .show = cable_plug_type_show, +}; + +static struct attribute *typec_cable_attrs[] = { + &dev_attr_active_cable.attr, + &dev_attr_plug_type.attr, + NULL +}; + +static struct attribute_group typec_cable_group = { + .attrs = typec_cable_attrs, +}; + +static const struct attribute_group *typec_cable_groups[] = { + &typec_cable_group, + NULL +}; + +static struct device_type typec_cable_dev_type = { + .name = "typec_cable_device", + .groups = typec_cable_groups, + .release = typec_dev_release, +}; + +static int typec_add_cable(struct typec_port *port, struct typec_cable *cable) +{ + struct device *dev = &cable->dev; + int ret; + + dev->class = &typec_class; + dev->parent = &port->dev; + dev->type = &typec_cable_dev_type; + dev_set_name(dev, "%s-cable", dev_name(&port->dev)); + + ret = device_register(dev); + if (ret) { + put_device(dev); + return ret; + } + + /* Plug1 */ + if (!cable->active) + return 0; + + cable->plug[0].index = 1; + ret = typec_add_plug(port, &cable->plug[0]); + if (ret) { + device_unregister(dev); + return ret; + } + + /* Plug2 */ + if (!cable->sop_pp_controller) + return 0; + + cable->plug[1].index = 2; + ret = typec_add_plug(port, &cable->plug[1]); + if (ret) { + typec_remove_plug(&cable->plug[0]); + device_unregister(dev); + return ret; + } + + port->cable = cable; + return 0; +} + +static void typec_remove_cable(struct typec_port *port) +{ + if (port->cable->active) { + typec_remove_plug(&port->cable->plug[0]); + if (port->cable->sop_pp_controller) + typec_remove_plug(&port->cable->plug[1]); + } + device_unregister(&port->cable->dev); +} + +static void typec_init_roles(struct typec_port *port) +{ + if (port->prefer_role < 0) + return; + + if (port->prefer_role == TYPEC_SOURCE) { + port->data_role = TYPEC_HOST; + port->pwr_role = TYPEC_SOURCE; + port->vconn_role = TYPEC_SOURCE; + } else { + /* Device mode as default also by default with DRP ports */ + port->data_role = TYPEC_DEVICE; + port->pwr_role = TYPEC_SINK; + port->vconn_role = TYPEC_SINK; + } +} + +/* ------------------------------------------------------------------------- */ +/* API for the port drivers */ + +int typec_connect(struct typec_port *port, struct typec_connection *con) +{ + int ret; + + if (!con->partner && !con->cable) + return -EINVAL; + + port->connected = 1; + port->data_role = con->data_role; + port->pwr_role = con->pwr_role; + port->vconn_role = con->vconn_role; + port->pwr_opmode = con->pwr_opmode; + + kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); + + if (con->cable) { + ret = typec_add_cable(port, con->cable); + if (ret) + return ret; + } + + if (con->partner) { + ret = typec_add_partner(port, con->partner); + if (ret) { + if (con->cable) + typec_remove_cable(port); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(typec_connect); + +void typec_disconnect(struct typec_port *port) +{ + if (port->partner) + typec_remove_partner(port); + + if (port->cable) + typec_remove_cable(port); + + port->connected = 0; + port->partner = NULL; + port->cable = NULL; + + port->pwr_opmode = TYPEC_PWR_MODE_USB; + + typec_init_roles(port); + + kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); +} +EXPORT_SYMBOL_GPL(typec_disconnect); + +/* --------------------------------------- */ +/* Driver callbacks to report role updates */ + +void typec_set_data_role(struct typec_port *port, enum typec_data_role role) +{ + mutex_lock(&port->lock); + port->data_role = role; + sysfs_notify(&port->dev.kobj, NULL, "current_data_role"); + mutex_unlock(&port->lock); +} +EXPORT_SYMBOL(typec_set_data_role); + +void typec_set_pwr_role(struct typec_port *port, enum typec_role role) +{ + mutex_lock(&port->lock); + port->pwr_role = role; + sysfs_notify(&port->dev.kobj, NULL, "current_power_role"); + mutex_unlock(&port->lock); +} +EXPORT_SYMBOL(typec_set_pwr_role); + +void typec_set_vconn_role(struct typec_port *port, enum typec_role role) +{ + mutex_lock(&port->lock); + port->vconn_role = role; + sysfs_notify(&port->dev.kobj, NULL, "current_vconn_role"); + mutex_unlock(&port->lock); +} +EXPORT_SYMBOL(typec_set_vconn_role); + +void typec_set_pwr_opmode(struct typec_port *port, + enum typec_pwr_opmode opmode) +{ + mutex_lock(&port->lock); + port->pwr_opmode = opmode; + sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode"); + mutex_unlock(&port->lock); +} +EXPORT_SYMBOL(typec_set_pwr_opmode); + +/* -------------------------------- */ +/* Alternate Modes */ + +/* + * typec_altmode_update_active - Notify about Enter/Exit mode + * @alt: Handle to the Alternate Mode + * @mode: Mode id + * @active: True when the mode has been enterred + */ +void typec_altmode_update_active(struct typec_altmode *alt, int mode, + bool active) +{ + struct typec_port *port = typec_altmode2port(alt); + struct typec_mode *m = alt->modes + mode; + char dir[6]; + + mutex_lock(&port->lock); + m->active = active; + sprintf(dir, "mode%d", mode); + sysfs_notify(&alt->dev.kobj, dir, "active"); + mutex_unlock(&port->lock); +} +EXPORT_SYMBOL(typec_altmode_update_active); + +static struct device_type typec_port_dev_type; + +/* + * typec_altmode2port - Alternate Mode to USB Type-C port + * @alt: The Alternate Mode + * + * Returns the port that the cable plug or partner with @alt is connected to. + */ +struct typec_port *typec_altmode2port(struct typec_altmode *alt) +{ + if (alt->dev.parent->type == &typec_plug_dev_type) + return to_typec_port(alt->dev.parent->parent->parent); + if (alt->dev.parent->type == &typec_partner_dev_type) + return to_typec_port(alt->dev.parent->parent); + if (alt->dev.parent->type == &typec_port_dev_type) + return to_typec_port(alt->dev.parent); + + return NULL; +} +EXPORT_SYMBOL_GPL(typec_altmode2port); + +static void typec_altmode_release(struct device *dev) +{ + struct typec_altmode *alt = to_altmode(dev); + + kfree(alt->mode_groups); +} + +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); + struct typec_port *port = typec_altmode2port(mode->alt_mode); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "0x%08x\n", mode->vdo); + mutex_unlock(&port->lock); + + return ret; +} + +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); + struct typec_port *port = typec_altmode2port(mode->alt_mode); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "%s\n", mode->desc ? mode->desc : ""); + mutex_unlock(&port->lock); + + return ret; +} + +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); + struct typec_port *port = typec_altmode2port(mode->alt_mode); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "%d\n", mode->active); + mutex_unlock(&port->lock); + + return ret; +} + +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; + + ret = kstrtobool(buf, &activate); + if (ret) + return ret; + + if (activate > 1) + return -EINVAL; + + mutex_lock(&port->lock); + ret = port->cap->activate_mode(mode->alt_mode, mode->index, activate); + if (!ret) { + mode->active = activate; + ret = size; + } + mutex_unlock(&port->lock); + + return ret; +} + +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); + struct typec_port *port = typec_altmode2port(mode->alt_mode); + ssize_t ret; + + mutex_lock(&port->lock); + 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; + } + mutex_unlock(&port->lock); + + return ret; +} + +static void typec_init_modes(struct typec_altmode *alt, int is_port) +{ + struct typec_mode *mode = alt->modes; + int i; + + for (i = 0; i < alt->n_modes; i++, mode++) { + mode->alt_mode = alt; + mode->index = i; + sprintf(mode->group_name, "mode%d", i); + + sysfs_attr_init(&mode->vdo_attr.attr); + mode->vdo_attr.attr.name = "vdo"; + mode->vdo_attr.attr.mode = S_IRUGO; + 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 = S_IRUGO; + 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 = S_IWUSR | S_IRUGO; + 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 = S_IRUGO; + 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 int +typec_add_altmode(struct device *parent, struct typec_altmode *alt, int is_port) +{ + struct device *dev = &alt->dev; + int ret; + + alt->mode_groups = kcalloc(alt->n_modes + 1, + sizeof(struct attibute_group *), GFP_KERNEL); + if (!alt->mode_groups) + return -ENOMEM; + + typec_init_modes(alt, is_port); + + dev->groups = alt->mode_groups; + dev->release = typec_altmode_release; + dev->parent = parent; + /* TODO: if (!is_port) dev->bus = &typec_altmode_bus; */ + + dev_set_name(dev, "%s.svid:%04x", dev_name(parent), alt->svid); + + ret = device_register(dev); + if (ret) { + put_device(dev); + kfree(alt->mode_groups); + return ret; + } + + return 0; +} + +static int __typec_register_altmodes(struct device *parent, + struct typec_altmode *alt_modes, + int is_port) +{ + struct typec_altmode *alt; + int index; + int ret; + + if (!alt_modes) + return 0; + + for (alt = alt_modes, index = 0; alt->svid; alt++, index++) { + ret = typec_add_altmode(parent, alt, is_port); + if (ret) + goto err; + } + + return 0; +err: + for (alt = alt_modes + index; index; alt--, index--) + device_unregister(&alt->dev); + + return ret; +} + +int typec_register_altmodes(struct device *dev, struct typec_altmode *alt_modes) +{ + if (dev->type == &typec_partner_dev_type) { + struct typec_partner *p = container_of(dev, + struct typec_partner, + dev); + p->alt_modes = alt_modes; + } else if (dev->type == &typec_plug_dev_type) { + struct typec_plug *p = container_of(dev, struct typec_plug, + dev); + p->alt_modes = alt_modes; + } else { + return -ENODEV; + } + + return __typec_register_altmodes(dev, alt_modes, false); +} +EXPORT_SYMBOL_GPL(typec_register_altmodes); + +void typec_unregister_altmodes(struct device *dev) +{ + struct typec_altmode *alt_modes = NULL; + struct typec_altmode *alt; + + if (dev->type == &typec_partner_dev_type) { + struct typec_partner *p = container_of(dev, + struct typec_partner, + dev); + alt_modes = p->alt_modes; + } else if (dev->type == &typec_plug_dev_type) { + struct typec_plug *p = container_of(dev, struct typec_plug, + dev); + alt_modes = p->alt_modes; + } + + if (!alt_modes) + return; + + for (alt = alt_modes; alt->svid; alt++) + device_unregister(&alt->dev); +} +EXPORT_SYMBOL_GPL(typec_unregister_altmodes); + +/* ------------------------------------------------------------------------- */ + +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); + enum typec_role role; + int ret; + + mutex_lock(&port->lock); + + if (port->cap->type != TYPEC_PORT_DRP) { + dev_dbg(dev, "Preferred role only supported with DRP ports\n"); + ret = -EOPNOTSUPP; + goto out; + } + + if (!port->cap->try_role) { + dev_dbg(dev, "Setting preferred role not supported\n"); + ret = -EOPNOTSUPP; + goto out; + } + + ret = match_string(typec_roles, ARRAY_SIZE(typec_roles), buf); + if (ret < 0) { + port->prefer_role = -1; + ret = size; + goto out; + } + + role = ret; + + ret = port->cap->try_role(port->cap, role); + if (ret) + goto out; + + port->prefer_role = role; + ret = size; +out: + mutex_unlock(&port->lock); + return ret; +} + +static ssize_t +preferred_role_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct typec_port *port = to_typec_port(dev); + ssize_t ret = 0; + + mutex_lock(&port->lock); + + if (port->prefer_role < 0) + goto out; + + ret = sprintf(buf, "%s\n", typec_roles[port->prefer_role]); +out: + mutex_unlock(&port->lock); + return ret; +} +static DEVICE_ATTR_RW(preferred_role); + +static ssize_t +current_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 = size; + + mutex_lock(&port->lock); + + if (port->cap->type != TYPEC_PORT_DRP) { + dev_dbg(dev, "data role swap only supported with DRP ports\n"); + ret = -EOPNOTSUPP; + goto out; + } + + if (!port->cap->dr_set) { + dev_dbg(dev, "data role swapping not supported\n"); + ret = -EOPNOTSUPP; + goto out; + } + + if (!port->connected) + goto out; + + ret = match_string(typec_data_roles, ARRAY_SIZE(typec_data_roles), buf); + if (ret < 0) + goto out; + + ret = port->cap->dr_set(port->cap, ret); + if (ret) + goto out; + + ret = size; +out: + mutex_unlock(&port->lock); + return ret; +} + +static ssize_t +current_data_role_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct typec_port *port = to_typec_port(dev); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "%s\n", typec_data_roles[port->data_role]); + mutex_unlock(&port->lock); + + return ret; +} +static DEVICE_ATTR_RW(current_data_role); + +static ssize_t supported_data_roles_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct typec_port *port = to_typec_port(dev); + size_t ret; + + mutex_lock(&port->lock); + + if (port->cap->type == TYPEC_PORT_DRP) { + ret = sprintf(buf, "host, device\n"); + goto out; + } + + ret = sprintf(buf, "%s\n", typec_data_roles[port->data_role]); +out: + mutex_unlock(&port->lock); + return ret; +} +static DEVICE_ATTR_RO(supported_data_roles); + +static ssize_t current_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; + + mutex_lock(&port->lock); + + if (!port->cap->usb_pd) { + dev_dbg(dev, "power role swap only supported with USB PD\n"); + ret = -EOPNOTSUPP; + goto out; + } + + if (!port->cap->pr_set) { + dev_dbg(dev, "power role swapping not supported\n"); + ret = -EOPNOTSUPP; + goto out; + } + + if (port->pwr_opmode != TYPEC_PWR_MODE_PD) { + dev_dbg(dev, "partner unable to swap power role\n"); + ret = -EIO; + goto out; + } + + if (!port->connected) + goto out; + + ret = match_string(typec_roles, ARRAY_SIZE(typec_roles), buf); + if (ret < 0) + goto out; + + ret = port->cap->pr_set(port->cap, ret); + if (ret) + goto out; + + ret = size; +out: + mutex_unlock(&port->lock); + return ret; +} + +static ssize_t current_power_role_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct typec_port *port = to_typec_port(dev); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "%s\n", typec_roles[port->pwr_role]); + mutex_unlock(&port->lock); + + return ret; +} +static DEVICE_ATTR_RW(current_power_role); + +static ssize_t supported_power_roles_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct typec_port *port = to_typec_port(dev); + size_t ret; + + mutex_lock(&port->lock); + + if (port->cap->usb_pd || port->cap->type == TYPEC_PORT_DRP) { + ret = sprintf(buf, "source, sink\n"); + goto out; + } + + ret = sprintf(buf, "%s\n", typec_roles[port->pwr_role]); +out: + mutex_unlock(&port->lock); + return ret; +} +static DEVICE_ATTR_RO(supported_power_roles); + +static const char * const typec_pwr_opmodes[] = { + [TYPEC_PWR_MODE_USB] = "USB", + [TYPEC_PWR_MODE_BC1_2] = "BC1.2", + [TYPEC_PWR_MODE_1_5A] = "USB Type-C 1.5A", + [TYPEC_PWR_MODE_3_0A] = "USB Type-C 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); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]); + mutex_unlock(&port->lock); + + return ret; +} +static DEVICE_ATTR_RO(power_operation_mode); + +static ssize_t current_vconn_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; + + mutex_lock(&port->lock); + + if (!port->cap->usb_pd) { + dev_dbg(dev, "vconn swap only supported with USB PD\n"); + ret = -EOPNOTSUPP; + goto out; + } + + if (!port->cap->vconn_set) { + dev_dbg(dev, "vconn swapping not supported\n"); + ret = -EOPNOTSUPP; + goto out; + } + + ret = match_string(typec_roles, ARRAY_SIZE(typec_roles), buf); + if (ret < 0) + goto out; + + ret = port->cap->vconn_set(port->cap, ret); + if (ret) + goto out; + + ret = size; +out: + mutex_unlock(&port->lock); + return ret; +} + +static ssize_t current_vconn_role_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct typec_port *port = to_typec_port(dev); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "%s\n", typec_roles[port->vconn_role]); + mutex_unlock(&port->lock); + + return ret; +} +static DEVICE_ATTR_RW(current_vconn_role); + +static ssize_t supported_accessory_modes_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct typec_port *port = to_typec_port(dev); + enum typec_accessory *accessory; + ssize_t ret = 0; + int i; + + mutex_lock(&port->lock); + if (port->cap->accessory) + for (accessory = port->cap->accessory, i = 0; + i < port->cap->num_accessory; accessory++, i++) + ret += sprintf(buf, "%s\n", + typec_accessory_modes[*accessory]); + mutex_unlock(&port->lock); + + return ret; +} +static DEVICE_ATTR_RO(supported_accessory_modes); + +static ssize_t supports_usb_power_delivery_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct typec_port *port = to_typec_port(dev); + ssize_t ret; + + mutex_lock(&port->lock); + ret = sprintf(buf, "%d\n", port->cap->usb_pd); + mutex_unlock(&port->lock); + + return ret; +} +static DEVICE_ATTR_RO(supports_usb_power_delivery); + +static struct attribute *typec_attrs[] = { + &dev_attr_current_power_role.attr, + &dev_attr_current_vconn_role.attr, + &dev_attr_current_data_role.attr, + &dev_attr_power_operation_mode.attr, + &dev_attr_preferred_role.attr, + &dev_attr_supported_accessory_modes.attr, + &dev_attr_supported_data_roles.attr, + &dev_attr_supported_power_roles.attr, + &dev_attr_supports_usb_power_delivery.attr, + NULL, +}; + +static const struct attribute_group typec_group = { + .attrs = typec_attrs, +}; + +static const struct attribute_group *typec_groups[] = { + &typec_group, + NULL, +}; + +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 struct device_type typec_port_dev_type = { + .name = "typec_port", + .groups = typec_groups, + .uevent = typec_uevent, + .release = typec_release, +}; + +struct typec_port *typec_register_port(struct device *dev, + const struct typec_capability *cap) +{ + struct typec_port *port; + int ret; + int id; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return ERR_PTR(-ENOMEM); + + id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL); + if (id < 0) { + kfree(port); + return ERR_PTR(id); + } + + /* FIXME: a better approach for this */ + port->prefer_role = -1; + + port->id = id; + port->cap = cap; + port->dev.type = &typec_port_dev_type; + port->dev.class = &typec_class; + port->dev.parent = dev; + dev_set_name(&port->dev, "usbc%d", id); + mutex_init(&port->lock); + + typec_init_roles(port); + + ret = device_register(&port->dev); + if (ret) + goto reg_err; + + ret = __typec_register_altmodes(&port->dev, cap->alt_modes, true); + if (ret) + goto alt_err; + + return port; +alt_err: + device_unregister(&port->dev); +reg_err: + ida_simple_remove(&typec_index_ida, id); + put_device(&port->dev); + kfree(port); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(typec_register_port); + +void typec_unregister_port(struct typec_port *port) +{ + struct typec_altmode *alt; + + WARN_ON(port->connected); + + if (port->cap->alt_modes) + for (alt = port->cap->alt_modes; alt->svid; alt++) + device_unregister(&alt->dev); + device_unregister(&port->dev); +} +EXPORT_SYMBOL_GPL(typec_unregister_port); + +static int __init typec_init(void) +{ + return class_register(&typec_class); +} +subsys_initcall(typec_init); + +static void __exit typec_exit(void) +{ + class_unregister(&typec_class); +} +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 0000000..d89a59c --- /dev/null +++ b/include/linux/usb/typec.h @@ -0,0 +1,255 @@ + +#ifndef __LINUX_USB_TYPEC_H +#define __LINUX_USB_TYPEC_H + +#include <linux/device.h> +#include <linux/types.h> + +struct typec_port; + +enum typec_port_type { + TYPEC_PORT_DFP, + TYPEC_PORT_UFP, + TYPEC_PORT_DRP, +}; + +enum typec_partner_type { + TYPEC_PARTNER_USB, + TYPEC_PARTNER_CHARGER, + TYPEC_PARTNER_ALTMODE, + TYPEC_PARTNER_ACCESSORY, +}; + +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_BC1_2, + 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, + TYPEC_ACCESSORY_DAUDIO, +}; + +/* + * struct typec_mode - Individual Mode of an Alternate Mode + * @vdo: VDO returned by Discover Modes USB PD command + * @desc: Mode description + * @active: Tells if the mode is currently entered or not + * @index: Index of the mode + * @group_name: Name for the sysfs folder in form "mode<index>" + * @group: The sysfs group (folder) for the mode + * @attrs: The attributes for the sysfs group + * @vdo_attr: Device attribute to expose the VDO of the mode + * @desc_attr: Device attribute to expose the description of the mode + * @active_attr: Device attribute to expose active of the mode + * @roles: Only for ports. DRP if the mode is awailable in both roles + * @roles_attr: Device attribute, only for ports, to expose the supported roles + * + * Details about 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 is the mode currently active or not. + */ +struct typec_mode { + u32 vdo; + char *desc; + unsigned int active:1; + /* Only for ports */ + enum typec_port_type roles; + + struct typec_altmode *alt_mode; + + int index; + char group_name[8]; + struct attribute_group group; + struct attribute *attrs[5]; + struct device_attribute vdo_attr; + struct device_attribute desc_attr; + struct device_attribute active_attr; + /* Only for ports */ + struct device_attribute roles_attr; +}; + +/* + * struct typec_altmode - USB Type-C Alternate Mode + * @dev: struct device instance + * @name: Name for the Alternate Mode (optional) + * @svid: Standard or Vendor ID + * @n_modes: Number of modes + * @modes: Array of modes supported by the Alternat Mode + * @mode_groups: The modes as attribute groups to be exposed in sysfs + * + * 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 { + struct device dev; + char *name; + + u16 svid; + int n_modes; + struct typec_mode *modes; + + const struct attribute_group **mode_groups; +}; + +#define to_altmode(d) container_of(d, struct typec_altmode, dev) + +struct typec_port *typec_altmode2port(struct typec_altmode *); + +void typec_altmode_update_active(struct typec_altmode *alt, int mode, + bool active); + +int typec_register_altmodes(struct device *, struct typec_altmode *); +void typec_unregister_altmodes(struct device *); + +/* + * struct typec_plug - USB Type-C Cable Plug + * @dev: struct device instance + * @index: 1 for the plug connected to DFP and 2 for the plug connected to UFP + * @alt_modes: Alternate Modes the cable plug supports (null terminated) + * + * Represents USB Type-C Cable Plug. + */ +struct typec_plug { + struct device dev; + int index; + struct typec_altmode *alt_modes; +}; + +/* + * struct typec_cable - USB Type-C Cable + * @dev: struct device instance + * @type: The plug type from USB PD Cable VDO + * @active: Is the cable active or passive + * @sop_pp_controller: Tells whether both cable plugs are configurable or not + * @plug: The two plugs in the cable. + * + * Represents USB Type-C Cable attached to USB Type-C port. Two plugs are + * created if the cable has SOP Double Prime controller as defined in USB PD + * specification. Otherwise only one will be created if the cable is active. For + * passive cables no plugs are created. + */ +struct typec_cable { + struct device dev; + enum typec_plug_type type; + unsigned int active:1; + unsigned int sop_pp_controller:1; + /* REVISIT: What else needed? */ + + struct typec_plug plug[2]; +}; + +/* + * struct typec_partner - USB Type-C Partner + * @dev: struct device instance + * @type: Normal USB device, charger, Alternate Mode or Accessory + * @alt_modes: Alternate Modes the partner supports (null terminated) + * + * Details about a partner that is attached to USB Type-C port. + */ +struct typec_partner { + struct device dev; + enum typec_partner_type type; + enum typec_accessory accessory; + struct typec_altmode *alt_modes; +}; + +/* + * struct typec_capability - USB Type-C Port Capabilities + * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role) + * @usb_pd: USB Power Delivery support + * @accessory: Supported Accessory Modes + * @num_accessory: Number of supported Accessory Modes + * @alt_modes: Alternate Modes the connector supports (null terminated) + * @try_role: Set a fixed data role 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; + unsigned int usb_pd:1; + enum typec_accessory *accessory; + unsigned int num_accessory; + struct typec_altmode *alt_modes; + + int (*try_role)(const struct typec_capability *, + enum typec_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)(struct typec_altmode *, + int mode, int activate); +}; + +/* + * struct typec_connection - Details about USB Type-C port connection event + * @partner: The attached partner + * @cable: The attached cable + * @data_role: Initial USB data role (host or device) + * @pwr_role: Initial Power role (source or sink) + * @vconn_role: Initial VCONN role (source or sink) + * @pwr_opmode: The power mode of the connection + * + * All the relevant details about a connection event. Wrapper that is passed to + * typec_connect(). The context is copied when typec_connect() is called and the + * structure is not used for anything else. + */ +struct typec_connection { + struct typec_partner *partner; + struct typec_cable *cable; + + enum typec_data_role data_role; + enum typec_role pwr_role; + enum typec_role vconn_role; + enum typec_pwr_opmode pwr_opmode; +}; + +struct typec_port *typec_register_port(struct device *dev, + const struct typec_capability *cap); +void typec_unregister_port(struct typec_port *port); + +int typec_connect(struct typec_port *port, struct typec_connection *con); +void typec_disconnect(struct typec_port *port); + +/* Callbacks from driver */ + +void typec_set_data_role(struct typec_port *, enum typec_data_role); +void typec_set_pwr_role(struct typec_port *, enum typec_role); +void typec_set_vconn_role(struct typec_port *, enum typec_role); +void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode); + +#endif /* __LINUX_USB_TYPEC_H */ -- 2.8.1 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-21 14:51 ` [PATCHv3 1/2] usb: USB Type-C connector class Heikki Krogerus @ 2016-06-21 20:25 ` Oliver Neukum 2016-06-22 9:50 ` Heikki Krogerus 2016-06-22 21:54 ` Guenter Roeck ` (2 subsequent siblings) 3 siblings, 1 reply; 34+ messages in thread From: Oliver Neukum @ 2016-06-21 20:25 UTC (permalink / raw) To: Heikki Krogerus Cc: Greg KH, Guenter Roeck, Felipe Balbi, linux-kernel, linux-usb On Tue, 2016-06-21 at 17:51 +0300, Heikki Krogerus wrote: > +What: /sys/class/typec/<port>/supported_data_roles > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Lists the USB data roles, host or device, the port is > capable > + of supporting. On third thought, this is a problem. Looking at 4.4.8.1 DEVICE_CAPABILITIES (Required) of USB Type-C Port Controller Interface Specification we lack capability. A port that can do DRP is not the same thing as a port that can be switched between DFP and UFP. We cannot express that. Regards Oliver ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-21 20:25 ` Oliver Neukum @ 2016-06-22 9:50 ` Heikki Krogerus 2016-06-22 10:03 ` Heikki Krogerus 2016-06-22 10:14 ` Oliver Neukum 0 siblings, 2 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-22 9:50 UTC (permalink / raw) To: Oliver Neukum Cc: Greg KH, Guenter Roeck, Felipe Balbi, linux-kernel, linux-usb On Tue, Jun 21, 2016 at 10:25:05PM +0200, Oliver Neukum wrote: > On Tue, 2016-06-21 at 17:51 +0300, Heikki Krogerus wrote: > > +What: /sys/class/typec/<port>/supported_data_roles > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Lists the USB data roles, host or device, the port is > > capable > > + of supporting. > > On third thought, this is a problem. Looking at 4.4.8.1 > DEVICE_CAPABILITIES (Required) of USB Type-C Port Controller > Interface Specification we lack capability. > > A port that can do DRP is not the same thing as a port that > can be switched between DFP and UFP. We cannot express that. What do you mean? DRP means we support and are able to swap the data role, but it just does not mean we can act as both source and sink. And that information we already get from separate attribute: "supported_power_roles". But if the port is DRP, we will always be able to swap the data role between DFP and UFP. Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 9:50 ` Heikki Krogerus @ 2016-06-22 10:03 ` Heikki Krogerus 2016-06-22 10:21 ` Oliver Neukum 2016-06-22 10:14 ` Oliver Neukum 1 sibling, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-22 10:03 UTC (permalink / raw) To: Oliver Neukum Cc: Greg KH, Guenter Roeck, Felipe Balbi, linux-kernel, linux-usb On Wed, Jun 22, 2016 at 12:50:16PM +0300, Heikki Krogerus wrote: > On Tue, Jun 21, 2016 at 10:25:05PM +0200, Oliver Neukum wrote: > > On Tue, 2016-06-21 at 17:51 +0300, Heikki Krogerus wrote: > > > +What: /sys/class/typec/<port>/supported_data_roles > > > +Data: June 2016 > > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > > +Description: > > > + Lists the USB data roles, host or device, the port is > > > capable > > > + of supporting. > > > > On third thought, this is a problem. Looking at 4.4.8.1 > > DEVICE_CAPABILITIES (Required) of USB Type-C Port Controller > > Interface Specification we lack capability. > > > > A port that can do DRP is not the same thing as a port that > > can be switched between DFP and UFP. We cannot express that. > > What do you mean? DRP means we support and are able to swap the data > role, but it just does not mean we can act as both source and sink. And > that information we already get from separate attribute: > "supported_power_roles". > > But if the port is DRP, we will always be able to swap the data role > between DFP and UFP. Just to clarify: DRP as it's defined in Type-C spec < 1.2 means the data role, not power role. And that is what Universal Serial Bus Type-CTM Port Controller specification is based on. Please correct me if I'm wrong. Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 10:03 ` Heikki Krogerus @ 2016-06-22 10:21 ` Oliver Neukum 0 siblings, 0 replies; 34+ messages in thread From: Oliver Neukum @ 2016-06-22 10:21 UTC (permalink / raw) To: Heikki Krogerus Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Wed, 2016-06-22 at 13:03 +0300, Heikki Krogerus wrote: > On Wed, Jun 22, 2016 at 12:50:16PM +0300, Heikki Krogerus wrote: > > > But if the port is DRP, we will always be able to swap the data role > > between DFP and UFP. > > Just to clarify: DRP as it's defined in Type-C spec < 1.2 means the > data role, not power role. And that is what Universal Serial Bus > Type-CTM Port Controller specification is based on. Please correct me > if I'm wrong. Understood. That is exactly the problem. That spec defines two ways to support host and client. Regards Oliver ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 9:50 ` Heikki Krogerus 2016-06-22 10:03 ` Heikki Krogerus @ 2016-06-22 10:14 ` Oliver Neukum 2016-06-22 11:44 ` Heikki Krogerus 1 sibling, 1 reply; 34+ messages in thread From: Oliver Neukum @ 2016-06-22 10:14 UTC (permalink / raw) To: Heikki Krogerus Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Wed, 2016-06-22 at 12:50 +0300, Heikki Krogerus wrote: > On Tue, Jun 21, 2016 at 10:25:05PM +0200, Oliver Neukum wrote: > > On Tue, 2016-06-21 at 17:51 +0300, Heikki Krogerus wrote: > > > +What: /sys/class/typec/<port>/supported_data_roles > > > +Data: June 2016 > > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > > +Description: > > > + Lists the USB data roles, host or device, the port is > > > capable > > > + of supporting. > > > > On third thought, this is a problem. Looking at 4.4.8.1 > > DEVICE_CAPABILITIES (Required) of USB Type-C Port Controller > > Interface Specification we lack capability. > > > > A port that can do DRP is not the same thing as a port that > > can be switched between DFP and UFP. We cannot express that. > > What do you mean? DRP means we support and are able to swap the data No. That is the error. We support them concurrently. And that is not obvious. It is perfectly possible to support both but not concurrently. > role, but it just does not mean we can act as both source and sink. And > that information we already get from separate attribute: > "supported_power_roles". But it is different. Suppose we have a port that can be switched between UFP and DFP, as the spec defines. If it is switched to DFP and we plug in a DFP it will not work. UFP into UFP has the same result. Plugging it into a DRP will always work. It is true that both support host and device, but the capability of the ports is different. And that is not expressed. Regards Oliver ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 10:14 ` Oliver Neukum @ 2016-06-22 11:44 ` Heikki Krogerus 2016-06-22 13:47 ` Oliver Neukum 0 siblings, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-22 11:44 UTC (permalink / raw) To: Oliver Neukum Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Wed, Jun 22, 2016 at 12:14:55PM +0200, Oliver Neukum wrote: > On Wed, 2016-06-22 at 12:50 +0300, Heikki Krogerus wrote: > > On Tue, Jun 21, 2016 at 10:25:05PM +0200, Oliver Neukum wrote: > > > On Tue, 2016-06-21 at 17:51 +0300, Heikki Krogerus wrote: > > > > +What: /sys/class/typec/<port>/supported_data_roles > > > > +Data: June 2016 > > > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > > > +Description: > > > > + Lists the USB data roles, host or device, the port is > > > > capable > > > > + of supporting. > > > > > > On third thought, this is a problem. Looking at 4.4.8.1 > > > DEVICE_CAPABILITIES (Required) of USB Type-C Port Controller > > > Interface Specification we lack capability. > > > > > > A port that can do DRP is not the same thing as a port that > > > can be switched between DFP and UFP. We cannot express that. > > > > What do you mean? DRP means we support and are able to swap the data > > No. That is the error. We support them concurrently. And that is not > obvious. It is perfectly possible to support both but not concurrently. > > > role, but it just does not mean we can act as both source and sink. And > > that information we already get from separate attribute: > > "supported_power_roles". > > But it is different. Suppose we have a port that can be switched between > UFP and DFP, as the spec defines. If it is switched to DFP and we plug > in a DFP it will not work. UFP into UFP has the same result. > > Plugging it into a DRP will always work. > > It is true that both support host and device, but the capability of > the ports is different. And that is not expressed. Sorry but I don't think I understand? So if we can act only as UFP, the supported_data_roles will list: device If we can act only as DFP, the supported_data_roles will list: host If our port is DRD (which would be DRP in the port controller spec), the supported_power_roles will list: device, host And the power role, if the port is Source only, the supported_power_roles will list: source If the port is Sink only, the supported_power_roles will list: sink If our port is DRP, the supported_power_roles will list: source, sink What is there that is missing? We are able to express all the types of "Roles Supported" that the DEVICE_CAPABILITIES define, no? Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 11:44 ` Heikki Krogerus @ 2016-06-22 13:47 ` Oliver Neukum 2016-06-22 14:38 ` Heikki Krogerus 0 siblings, 1 reply; 34+ messages in thread From: Oliver Neukum @ 2016-06-22 13:47 UTC (permalink / raw) To: Heikki Krogerus Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Wed, 2016-06-22 at 14:44 +0300, Heikki Krogerus wrote: > If our port is DRD (which would be DRP in the port controller spec), > the supported_power_roles will list: > > device, host > > And the power role, if the port is Source only, the > supported_power_roles will list: > > source > > If the port is Sink only, the supported_power_roles will list: > > sink > > If our port is DRP, the supported_power_roles will list: > > source, sink > > What is there that is missing? We are able to express all the types of > "Roles Supported" that the DEVICE_CAPABILITIES define, no? No, because these are distinct in time. Some ports are DRP so they support device, host at the same time. Some ports can be switched between DFP and UFP they then either support host or device. But you lose the information that the ports can be switched. Regards Oliver ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 13:47 ` Oliver Neukum @ 2016-06-22 14:38 ` Heikki Krogerus 2016-06-22 16:44 ` Oliver Neukum 0 siblings, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-22 14:38 UTC (permalink / raw) To: Oliver Neukum Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Wed, Jun 22, 2016 at 03:47:03PM +0200, Oliver Neukum wrote: > On Wed, 2016-06-22 at 14:44 +0300, Heikki Krogerus wrote: > > If our port is DRD (which would be DRP in the port controller spec), > > the supported_power_roles will list: > > > > device, host > > > > And the power role, if the port is Source only, the > > supported_power_roles will list: > > > > source > > > > If the port is Sink only, the supported_power_roles will list: > > > > sink > > > > If our port is DRP, the supported_power_roles will list: > > > > source, sink > > > > What is there that is missing? We are able to express all the types of > > "Roles Supported" that the DEVICE_CAPABILITIES define, no? > > No, because these are distinct in time. Some ports are DRP so they > support > > device, host > > at the same time. Some ports can be switched between DFP and UFP > they then either support host or device. But you lose the information > that the ports can be switched. You can't ever be host and device at the same time. Just like you can't ever be source and sink at the same time. Are we now talking about how should a port be advertised to the partners? So basically, do you want to be able to program the port to be DFP only, UFP only or DRP from user space? Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 14:38 ` Heikki Krogerus @ 2016-06-22 16:44 ` Oliver Neukum 2016-06-23 8:23 ` Heikki Krogerus 0 siblings, 1 reply; 34+ messages in thread From: Oliver Neukum @ 2016-06-22 16:44 UTC (permalink / raw) To: Heikki Krogerus Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Wed, 2016-06-22 at 17:38 +0300, Heikki Krogerus wrote: > On Wed, Jun 22, 2016 at 03:47:03PM +0200, Oliver Neukum wrote: > > On Wed, 2016-06-22 at 14:44 +0300, Heikki Krogerus wrote: > > > If our port is DRD (which would be DRP in the port controller spec), > > > the supported_power_roles will list: > > > > > > device, host > > > > > > And the power role, if the port is Source only, the > > > supported_power_roles will list: > > > > > > source > > > > > > If the port is Sink only, the supported_power_roles will list: > > > > > > sink > > > > > > If our port is DRP, the supported_power_roles will list: > > > > > > source, sink > > > > > > What is there that is missing? We are able to express all the types of > > > "Roles Supported" that the DEVICE_CAPABILITIES define, no? > > > > No, because these are distinct in time. Some ports are DRP so they > > support > > > > device, host > > > > at the same time. Some ports can be switched between DFP and UFP > > they then either support host or device. But you lose the information > > that the ports can be switched. > > You can't ever be host and device at the same time. Just like you > can't ever be source and sink at the same time. True, but you can be able to become host and device at the same time. That is the purpose of a DRP port. And you can be able to become a host and be able to become a device. But not at the same time. These ports are switchable. The current API cannot express the difference. > Are we now talking about how should a port be advertised to the > partners? So basically, do you want to be able to program the port to > be DFP only, UFP only or DRP from user space? That would be cool, but according to the spec this is an unalterable attribute. Please look at section 4.4.8.1 It clearly describes different types of ports. We cannot express the differences between the types described there with the current API. Regards Oliver ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 16:44 ` Oliver Neukum @ 2016-06-23 8:23 ` Heikki Krogerus 2016-06-23 8:38 ` Oliver Neukum 0 siblings, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-23 8:23 UTC (permalink / raw) To: Oliver Neukum Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Wed, Jun 22, 2016 at 06:44:18PM +0200, Oliver Neukum wrote: > On Wed, 2016-06-22 at 17:38 +0300, Heikki Krogerus wrote: > > On Wed, Jun 22, 2016 at 03:47:03PM +0200, Oliver Neukum wrote: > > > On Wed, 2016-06-22 at 14:44 +0300, Heikki Krogerus wrote: > > > > If our port is DRD (which would be DRP in the port controller spec), > > > > the supported_power_roles will list: > > > > > > > > device, host > > > > > > > > And the power role, if the port is Source only, the > > > > supported_power_roles will list: > > > > > > > > source > > > > > > > > If the port is Sink only, the supported_power_roles will list: > > > > > > > > sink > > > > > > > > If our port is DRP, the supported_power_roles will list: > > > > > > > > source, sink > > > > > > > > What is there that is missing? We are able to express all the types of > > > > "Roles Supported" that the DEVICE_CAPABILITIES define, no? > > > > > > No, because these are distinct in time. Some ports are DRP so they > > > support > > > > > > device, host > > > > > > at the same time. Some ports can be switched between DFP and UFP > > > they then either support host or device. But you lose the information > > > that the ports can be switched. > > > > You can't ever be host and device at the same time. Just like you > > can't ever be source and sink at the same time. > > True, but you can be able to become host and device at the same time. No you can't.. > That is the purpose of a DRP port. No it's not. DRP means a port that can operate as _either_ Source (host) or Sink (device), but not at the same time.. > And you can be able to become a host and be able to become a device. > But not at the same time. These ports are switchable. > > The current API cannot express the difference. I think you have misunderstood something. The only case where the port can be dual-role is if it's set to be DRP. Otherwise it's Source only OR Sink only. The "Role Supported" bits only tell us how we can program for example the ROLE_CONTROL registers. I guess the "Roles Supported" bits in DEVICE_CAPABILITIES are not explained properly, so let's go over them here: 000b = Source _or_ Sink only 001b = Source only 010b = Sink only 011b = Sink only with support for autonomously detected accessory modes 100b = DRP only, and this I believe mean we can not program the port to be Sink only or Source only 101b = Source only OR Sink only OR DRP, plus ability to detect accessories and I guess also cables autonomously 110b = Source only OR Sink only OR DRP So where the spec lists "Source, Sink", it actually should have said "Source only OR Sink only". But you still have only the following options for a port: 1) Source only (host) 2) Sink only (device) 3) DRP (device, host) Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-23 8:23 ` Heikki Krogerus @ 2016-06-23 8:38 ` Oliver Neukum 2016-06-23 12:00 ` Heikki Krogerus 0 siblings, 1 reply; 34+ messages in thread From: Oliver Neukum @ 2016-06-23 8:38 UTC (permalink / raw) To: Heikki Krogerus Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Thu, 2016-06-23 at 11:23 +0300, Heikki Krogerus wrote: > On Wed, Jun 22, 2016 at 06:44:18PM +0200, Oliver Neukum wrote: > No it's not. DRP means a port that can operate as _either_ Source > (host) or Sink (device), but not at the same time.. Yes, but it is unclear what you will be after a connection and that's the point. > > And you can be able to become a host and be able to become a device. > > But not at the same time. These ports are switchable. > > > > The current API cannot express the difference. > > I think you have misunderstood something. The only case where the port > can be dual-role is if it's set to be DRP. Otherwise it's Source only > OR Sink only. > > The "Role Supported" bits only tell us how we can program for example > the ROLE_CONTROL registers. I guess the "Roles Supported" bits in > DEVICE_CAPABILITIES are not explained properly, so let's go over them > here: > > 000b = Source _or_ Sink only > 001b = Source only > 010b = Sink only > 011b = Sink only with support for autonomously detected accessory modes > 100b = DRP only, and this I believe mean we can not program the port > to be Sink only or Source only I think so, too. > 101b = Source only OR Sink only OR DRP, plus ability to detect > accessories and I guess also cables autonomously > 110b = Source only OR Sink only OR DRP > > So where the spec lists "Source, Sink", it actually should have said > "Source only OR Sink only". > > But you still have only the following options for a port: > 1) Source only (host) > 2) Sink only (device) > 3) DRP (device, host) Yes, so you can map "000b = Source _or_ Sink only" to host or device depending on the current setting. But then you lose the information that it can be changed. It either will look like "001b" or "010b". So we throw away information. And you map "100b = DRP only" and "101b" and "110b" to host, device which again drops information. Regards Oliver ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-23 8:38 ` Oliver Neukum @ 2016-06-23 12:00 ` Heikki Krogerus 2016-06-23 12:25 ` Roger Quadros 2016-06-23 13:29 ` Guenter Roeck 0 siblings, 2 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-23 12:00 UTC (permalink / raw) To: Oliver Neukum Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb Hi Oliver, On Thu, Jun 23, 2016 at 10:38:58AM +0200, Oliver Neukum wrote: > On Thu, 2016-06-23 at 11:23 +0300, Heikki Krogerus wrote: > > On Wed, Jun 22, 2016 at 06:44:18PM +0200, Oliver Neukum wrote: > > > No it's not. DRP means a port that can operate as _either_ Source > > (host) or Sink (device), but not at the same time.. > > Yes, but it is unclear what you will be after a connection > and that's the point. Which is a fact that we can do nothing about. The role after connection with DRP ports will be dictated by the partner or selected randomly in case the partner is also DRP. We can prefer a role, but that in the end guarantees nothing. So if the role that we end up with after connection (seen in current_data_role) does not satisfy us, all we can do is try to swap it. I'm not sure what is your point here. > > > And you can be able to become a host and be able to become a device. > > > But not at the same time. These ports are switchable. > > > > > > The current API cannot express the difference. > > > > I think you have misunderstood something. The only case where the port > > can be dual-role is if it's set to be DRP. Otherwise it's Source only > > OR Sink only. > > > > The "Role Supported" bits only tell us how we can program for example > > the ROLE_CONTROL registers. I guess the "Roles Supported" bits in > > DEVICE_CAPABILITIES are not explained properly, so let's go over them > > here: > > > > 000b = Source _or_ Sink only > > 001b = Source only > > 010b = Sink only > > 011b = Sink only with support for autonomously detected accessory modes > > 100b = DRP only, and this I believe mean we can not program the port > > to be Sink only or Source only > > I think so, too. > > > 101b = Source only OR Sink only OR DRP, plus ability to detect > > accessories and I guess also cables autonomously > > 110b = Source only OR Sink only OR DRP > > > > So where the spec lists "Source, Sink", it actually should have said > > "Source only OR Sink only". > > > > But you still have only the following options for a port: > > 1) Source only (host) > > 2) Sink only (device) > > 3) DRP (device, host) > > Yes, so you can map "000b = Source _or_ Sink only" to host or device > depending on the current setting. But then you lose the information > that it can be changed. No it can't. The idea with the Roles Supported bits is for the driver to be able to select the most appropriate role that fits the abilities of the platform. The configuration of the port after probing the port controller will never change. If you have initially configured the port to be Sink only (so device), it most likely means your platform can not act as Source even if the port controller would. And if you want to change the configuration of the port, for example if your platform is capable of supporting Source and Sink modes, but your port controller is not capable of supporting DRP (which would be pretty messed up situation) but instead forces you to choose between Sink and Source, you would in practice in any case have to unregister, reconfigure and register the port again. But in most cases the platform will not support all the capabilities the port controller will be capable of. If for example on your platform you have only USB host controller, it just means you will have to have port controller that returns either 000b, 001b, 101b or 110b in the supported roles bits. Otherwise it will no be usable on your platform. > So we throw away information. > > And you map "100b = DRP only" and "101b" and "110b" to host, device No I don't. If our platform can only support Sink mode, value "100b" will not work and can not be ever registered, and values "101b" and "110b" will report "device" in supported_data_roles. And it is not the class that defines the capabilities of a port. They are defined by the drivers that register the ports. > which again drops information. There is no use in knowing details about the port controller capabilities like if a port could be configured to be Source or Sink only instead of just DRP from the typec class point of view. Those details are port controller specific, and completely out side the scope of the class driver. Not all USB Type-C PHYs will be port controllers and not all ports registered with the class will even have a PHY to deal with. This means we will not even always be able to read the same kinds of details of the port like we are with port controllers. So if you want to get the capabilities of the port controller in use, the port controller driver will have to expose them to user space, not the class. Br, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-23 12:00 ` Heikki Krogerus @ 2016-06-23 12:25 ` Roger Quadros 2016-06-23 13:11 ` Heikki Krogerus 2016-06-23 13:29 ` Guenter Roeck 1 sibling, 1 reply; 34+ messages in thread From: Roger Quadros @ 2016-06-23 12:25 UTC (permalink / raw) To: Heikki Krogerus, Oliver Neukum Cc: Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb Hi, On 23/06/16 15:00, Heikki Krogerus wrote: > Hi Oliver, > > On Thu, Jun 23, 2016 at 10:38:58AM +0200, Oliver Neukum wrote: >> On Thu, 2016-06-23 at 11:23 +0300, Heikki Krogerus wrote: >>> On Wed, Jun 22, 2016 at 06:44:18PM +0200, Oliver Neukum wrote: >> >>> No it's not. DRP means a port that can operate as _either_ Source >>> (host) or Sink (device), but not at the same time.. >> >> Yes, but it is unclear what you will be after a connection >> and that's the point. > > Which is a fact that we can do nothing about. The role after > connection with DRP ports will be dictated by the partner or selected > randomly in case the partner is also DRP. We can prefer a role, but > that in the end guarantees nothing. So if the role that we end up with > after connection (seen in current_data_role) does not satisfy us, all > we can do is try to swap it. > > I'm not sure what is your point here. What if the application wants to know exactly what role the device is operating in at the current moment? We need to have 2 distinct parameters. 1) supported_modes : host, device, host or device 2) current_mode: host, device, disconnected -- cheers, -roger ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-23 12:25 ` Roger Quadros @ 2016-06-23 13:11 ` Heikki Krogerus 0 siblings, 0 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-23 13:11 UTC (permalink / raw) To: Roger Quadros Cc: Oliver Neukum, Felipe Balbi, Greg KH, Guenter Roeck, linux-kernel, linux-usb On Thu, Jun 23, 2016 at 03:25:46PM +0300, Roger Quadros wrote: > Hi, > > On 23/06/16 15:00, Heikki Krogerus wrote: > > Hi Oliver, > > > > On Thu, Jun 23, 2016 at 10:38:58AM +0200, Oliver Neukum wrote: > >> On Thu, 2016-06-23 at 11:23 +0300, Heikki Krogerus wrote: > >>> On Wed, Jun 22, 2016 at 06:44:18PM +0200, Oliver Neukum wrote: > >> > >>> No it's not. DRP means a port that can operate as _either_ Source > >>> (host) or Sink (device), but not at the same time.. > >> > >> Yes, but it is unclear what you will be after a connection > >> and that's the point. > > > > Which is a fact that we can do nothing about. The role after > > connection with DRP ports will be dictated by the partner or selected > > randomly in case the partner is also DRP. We can prefer a role, but > > that in the end guarantees nothing. So if the role that we end up with > > after connection (seen in current_data_role) does not satisfy us, all > > we can do is try to swap it. > > > > I'm not sure what is your point here. > > What if the application wants to know exactly what role the device is > operating in at the current moment? > > We need to have 2 distinct parameters. > > 1) supported_modes : host, device, host or device > 2) current_mode: host, device, disconnected And we already do. But that is not the topic of this thread. Oliver I believe feels that we are not presenting all the capabilities of the ports. Cheers, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-23 12:00 ` Heikki Krogerus 2016-06-23 12:25 ` Roger Quadros @ 2016-06-23 13:29 ` Guenter Roeck 1 sibling, 0 replies; 34+ messages in thread From: Guenter Roeck @ 2016-06-23 13:29 UTC (permalink / raw) To: Heikki Krogerus, Oliver Neukum Cc: Felipe Balbi, Greg KH, linux-kernel, linux-usb On 06/23/2016 05:00 AM, Heikki Krogerus wrote: > Hi Oliver, > > On Thu, Jun 23, 2016 at 10:38:58AM +0200, Oliver Neukum wrote: >> On Thu, 2016-06-23 at 11:23 +0300, Heikki Krogerus wrote: >>> On Wed, Jun 22, 2016 at 06:44:18PM +0200, Oliver Neukum wrote: >> >>> No it's not. DRP means a port that can operate as _either_ Source >>> (host) or Sink (device), but not at the same time.. >> >> Yes, but it is unclear what you will be after a connection >> and that's the point. > > Which is a fact that we can do nothing about. The role after > connection with DRP ports will be dictated by the partner or selected > randomly in case the partner is also DRP. We can prefer a role, but > that in the end guarantees nothing. So if the role that we end up with > after connection (seen in current_data_role) does not satisfy us, all > we can do is try to swap it. > > I'm not sure what is your point here. > >>>> And you can be able to become a host and be able to become a device. >>>> But not at the same time. These ports are switchable. >>>> >>>> The current API cannot express the difference. >>> >>> I think you have misunderstood something. The only case where the port >>> can be dual-role is if it's set to be DRP. Otherwise it's Source only >>> OR Sink only. >>> >>> The "Role Supported" bits only tell us how we can program for example >>> the ROLE_CONTROL registers. I guess the "Roles Supported" bits in >>> DEVICE_CAPABILITIES are not explained properly, so let's go over them >>> here: >>> >>> 000b = Source _or_ Sink only >>> 001b = Source only >>> 010b = Sink only >>> 011b = Sink only with support for autonomously detected accessory modes >>> 100b = DRP only, and this I believe mean we can not program the port >>> to be Sink only or Source only >> >> I think so, too. >> >>> 101b = Source only OR Sink only OR DRP, plus ability to detect >>> accessories and I guess also cables autonomously >>> 110b = Source only OR Sink only OR DRP >>> >>> So where the spec lists "Source, Sink", it actually should have said >>> "Source only OR Sink only". >>> >>> But you still have only the following options for a port: >>> 1) Source only (host) >>> 2) Sink only (device) >>> 3) DRP (device, host) >> >> Yes, so you can map "000b = Source _or_ Sink only" to host or device >> depending on the current setting. But then you lose the information >> that it can be changed. > > No it can't. The idea with the Roles Supported bits is for the driver > to be able to select the most appropriate role that fits the abilities > of the platform. > > The configuration of the port after probing the port controller will > never change. If you have initially configured the port to be Sink > only (so device), it most likely means your platform can not act as > Source even if the port controller would. > > And if you want to change the configuration of the port, for example > if your platform is capable of supporting Source and Sink modes, but > your port controller is not capable of supporting DRP (which would be > pretty messed up situation) but instead forces you to choose between > Sink and Source, you would in practice in any case have to unregister, > reconfigure and register the port again. > > But in most cases the platform will not support all the capabilities > the port controller will be capable of. If for example on your > platform you have only USB host controller, it just means you will > have to have port controller that returns either 000b, 001b, 101b or > 110b in the supported roles bits. Otherwise it will no be usable on > your platform. > >> So we throw away information. >> >> And you map "100b = DRP only" and "101b" and "110b" to host, device > > No I don't. If our platform can only support Sink mode, value "100b" > will not work and can not be ever registered, and values "101b" and > "110b" will report "device" in supported_data_roles. > > And it is not the class that defines the capabilities of a port. > They are defined by the drivers that register the ports. > >> which again drops information. > > There is no use in knowing details about the port controller > capabilities like if a port could be configured to be Source or Sink > only instead of just DRP from the typec class point of view. Those > details are port controller specific, and completely out side the > scope of the class driver. Not all USB Type-C PHYs will be port > controllers and not all ports registered with the class will even have > a PHY to deal with. This means we will not even always be able to read > the same kinds of details of the port like we are with port > controllers. > > So if you want to get the capabilities of the port controller in use, > the port controller driver will have to expose them to user space, not > the class. > Agreed. Guenter ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-21 14:51 ` [PATCHv3 1/2] usb: USB Type-C connector class Heikki Krogerus 2016-06-21 20:25 ` Oliver Neukum @ 2016-06-22 21:54 ` Guenter Roeck 2016-06-23 8:25 ` Heikki Krogerus 2016-06-23 11:53 ` Roger Quadros [not found] ` <CAOiXhaKhPfY0Bz8TsZMFQsgLHZZ01DwZ=TPcXtH2nYvHx3PqVA@mail.gmail.com> 3 siblings, 1 reply; 34+ messages in thread From: Guenter Roeck @ 2016-06-22 21:54 UTC (permalink / raw) To: Heikki Krogerus Cc: Greg KH, Oliver Neukum, Felipe Balbi, linux-kernel, linux-usb Hi, On Tue, Jun 21, 2016 at 05:51:50PM +0300, Heikki Krogerus wrote: > 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 USB PD is > available, also control over power role swapping and > Alternate Modes. > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> > --- [ ... ] > + > +static void typec_remove_partner(struct typec_port *port) > +{ > + WARN_ON(port->partner->alt_modes); You are setting partner->alt_modes in typec_register_altmodes(), but you don't clear it in typec_unregister_altmodes(). Does this work for you ? I always get the warning when I remove a cable. Thanks, Guenter ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-22 21:54 ` Guenter Roeck @ 2016-06-23 8:25 ` Heikki Krogerus 0 siblings, 0 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-23 8:25 UTC (permalink / raw) To: Guenter Roeck Cc: Greg KH, Oliver Neukum, Felipe Balbi, linux-kernel, linux-usb Hi, On Wed, Jun 22, 2016 at 02:54:28PM -0700, Guenter Roeck wrote: > Hi, > > > + > > +static void typec_remove_partner(struct typec_port *port) > > +{ > > + WARN_ON(port->partner->alt_modes); > > You are setting partner->alt_modes in typec_register_altmodes(), > but you don't clear it in typec_unregister_altmodes(). > > Does this work for you ? I always get the warning when I remove a cable. Damn it.. I have managed to just ignore the warning. Yeah, this has to be fixed. Sorry about that. Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-21 14:51 ` [PATCHv3 1/2] usb: USB Type-C connector class Heikki Krogerus 2016-06-21 20:25 ` Oliver Neukum 2016-06-22 21:54 ` Guenter Roeck @ 2016-06-23 11:53 ` Roger Quadros 2016-06-23 13:08 ` Heikki Krogerus [not found] ` <CAOiXhaKhPfY0Bz8TsZMFQsgLHZZ01DwZ=TPcXtH2nYvHx3PqVA@mail.gmail.com> 3 siblings, 1 reply; 34+ messages in thread From: Roger Quadros @ 2016-06-23 11:53 UTC (permalink / raw) To: Heikki Krogerus, Greg KH, Guenter Roeck, Oliver Neukum Cc: Felipe Balbi, linux-kernel, linux-usb Hi Heikki, On 21/06/16 17:51, Heikki Krogerus wrote: > 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 USB PD is s/PD/PD (Power Delivery) > available, also control over power role swapping and > Alternate Modes. > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> > --- > Documentation/ABI/testing/sysfs-class-typec | 163 ++++ > Documentation/usb/typec.txt | 101 +++ > 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 | 1173 +++++++++++++++++++++++++++ > include/linux/usb/typec.h | 255 ++++++ > 9 files changed, 1713 insertions(+) > create mode 100644 Documentation/ABI/testing/sysfs-class-typec > create mode 100644 Documentation/usb/typec.txt > 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 0000000..ce577f3 > --- /dev/null > +++ b/Documentation/ABI/testing/sysfs-class-typec > @@ -0,0 +1,163 @@ > +USB Type-C port devices (eg. /sys/class/typec/usbc0/) > + > +What: /sys/class/typec/<port>/current_data_role > +Data: June 2016 s/Data/Date everywhere in this patch. > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + The current USB data role the port is operating in. This > + attribute can be used for requestion data role swapping on th s/requestion/requesting s/th/the > + port. Is it better to list all the values that can be here with a short note for each? Same for all properties below? Otherwise as a user I have no clue as to what all values I can set this to. > + > +What: /sys/class/typec/<port>/current_power_role > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + The current power role, source or sink, of the port. This > + attribute can be used to request power role swap on the port > + when USB Power Delivery is available. So if it is not yet available, why add this now? > + > +What: /sys/class/typec/<port>/current_vconn_role > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows the current VCONN role, source or sink, of the port. This > + attribute can be used to request vconn role swap on the port s/vconn/VCONN > + when USB Power Delivery is available. Why add if not yet available? > + > +What: /sys/class/typec/<port>/power_operation_mode > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows the current power power mode the port is in. Reads as on s/on/one > + of the following: > + - USB - Normal power levels defined in USB specifications > + - BC1.2 - Power levels defined in Battery Charging Specification > + v1.2 > + - USB Type-C 1.5A - Higher 1.5A current defined in USB Type-C > + specification. > + - USB Type-C 3.0A - Higher 3A current defined in USB Type-C > + specification. > + - USB Power Delivery - The voltages and currents defined in USB > + Power Delivery specification What would it show when the port is disconnected? Instead, is it somehow possible to list the actual negotiated current (in mA) here or in some other property, if you want to know the mode as well? > + > +What: /sys/class/typec/<port>/preferred_role > +Data: June 2016 > +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. What would be the default setting? > + > +What: /sys/class/typec/<port>/supported_accessory_modes > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Lists the Accessory Modes, defined in the USB Type-C > + specification, the port supports. > + > +What: /sys/class/typec/<port>/supported_data_roles > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Lists the USB data roles, host or device, the port is capable > + of supporting. Can't it support both e.g in DRP case? > + > +What: /sys/class/typec/<port>/supported_power_roles > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Lists the power roles, source and/or sink, the port is capable > + of supporting. > + > +What: /sys/class/typec/<port>/supports_usb_power_delivery > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows if the port support USB Power Delivery. s/support/supports > + > + > +USB Type-C partner devices (eg. /sys/class/typec/usbc0-partner/) > + > +What: /sys/class/typec/<port>-partner/accessory <port>-partner/ or <port>/partner ? > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows the name of the Accessory Mode if the partner attached to > + the port is an accessory. Otherwise shows nothing. > + > +What: /sys/class/typec/<port>-partner/type > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows the type of the partner. Can be one of the following: > + - USB - When the partner is normal USB host/peripheral. > + - Charger - When the partner has been identified as dedicated > + charger. > + - Alternate Mode - When the partner supports Alternate Modes. > + - Accessory - When the partner is one of the accessories with > + specific Accessory Mode defined in USB Type-C > + specification. > + > + > +USB Type-C cable devices (eg. /sys/class/typec/usbc0-cable/) > + > +Note: The two cable plugs will have their own devices presenting when available I didn't get this part. How come two cable plugs can have 2 devices? presenting what? > +(eg. /sys/class/typec/usbc0-plug0). Both plugs may have their own active > +alternate modes as described in USB Type-C and USB Power Delivery > +specifications. > + > +What: /sys/class/typec/<port>-cable/active <port>-cable/ or <port>/cable ? > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows if the cable is active or passive. Only active cables can > + have configurable alternate modes, therefore only active cables > + will have plug devices. > + > +What: /sys/class/typec/<port>-cable/plug_type > +Data: June 2016 > +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 - USB Type-C > + Captive - Non-standard > + > + > +Alternate Mode devices (For example, > +/sys/class/typec/usbc0-partner/usbc0-partner.svid:xxxx/) Why should it show usbc0-partner twice? > + > +What: /sys/class/typec/<dev>/<dev>.svid:<svid>/<mode>/active > +Data: June 2016 > +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. > + > +What: /sys/class/typec/<dev>/<dev>.svid:<svid>/<mode>/description > +Data: June 2016 > +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/<dev>/<dev>.svid:<svid>/<mode>/vdo > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows the VDO in hexadecimal returned from the Discover Modes > + command. > + > +What: /sys/class/typec/<port>/<port>.svid:<svid>/<mode>/supported_roles > +Data: June 2016 > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > +Description: > + Shows the roles, source or sink, the mode is supported with. > + > + 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. > diff --git a/Documentation/usb/typec.txt b/Documentation/usb/typec.txt > new file mode 100644 > index 0000000..ddeda97 > --- /dev/null > +++ b/Documentation/usb/typec.txt > @@ -0,0 +1,101 @@ > +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 > +expect the user space interface implementation in hope that it can be utilized s/expect/except/ > +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 offers the user space control > +over the roles and alternate modes they support 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. > + > + > +Interface > +--------- > +Every port will be presented as its own device under /sys/class/typec/. The > +first port will be named "usbc0", the second "usbc1" and so on. We already know it is typec since it sits in /sys/class/typec Why not just call the instances "0", "1" 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. The > +partner attached to port "usbc0" will be named "usbc0-partner". Can the partner exist without the port? If not the partner should be located within the port directory. > + > +The cable and the two plugs on it may also be optionally be presented as their > +own devices under /sys/class/typec/. The cable attached to the port "usbc0" port > +will be named usbc0-cable and the plug on the SOP Prime end (see USB Power > +Delivery Specification ch. 2.4) will be named "usbc-plug0" and on the SOP Double > +Prime end "usbc0-plug1". If cables and plugs can't exist without the port they must come up within the port directory. > + > +If the port, partner or cable plug support Alternate Modes, every Alternate Mode > +SVID will have their own device describing them. The Alternate Modes will not be > +attached to the typec class. For the port's "usbc0" partner, the Alternate Modes > +would have devices presented under /sys/class/typec/usbc0-partner/. Every mode > +that is supported will have its own group under the Alternate Mode device named > +"mode<id>". For example /sys/class/typec/usbc0/usbc0.svid:xxxx/mode0/. The > +requests for entering/exiting the modes happens with the "active" attribute in > +that group. > + > + > +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: > + > +struct typec_port *typec_register_port(struct device *dev, > + const struct typec_capability *cap); > + > +The class will provide handle to struct typec_port on success and ERR_PTR on > +failure. The un-registration of the port happens with the following API: > + > +void typec_unregister_port(struct typec_port *port); > + > + > +* Notifications > + > +When connection happens on a port, the port driver fills struct typec_connection > +which is passed to the class. The class provides the following API for reporting > +connection/disconnection: > + > +int typec_connect(struct typec_port *port, struct typec_connection *); > +void typec_disconnect(struct typec_port *); > + > +When the partner end has executed a role change, the port driver uses the > +following APIs to report it to the class: > + > +void typec_set_data_role(struct typec_port *, enum typec_data_role); > +void typec_set_pwr_role(struct typec_port *, enum typec_role); > +void typec_set_vconn_role(struct typec_port *, enum typec_role); > +void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode); > + > + > +* Alternate Modes > + > +After connection, the port drivers register the alternate modes the partner > +and/or cable plugs support. And before reporting disconnection, the port driver > +_must_ unregister all the alternate modes registered for the partner and cable > +plugs. The API takes the struct device of the partner or the cable plug as > +parameter: > + > +int typec_register_altmodes(struct device *, struct typec_altmode *); > +void typec_unregister_altmodes(struct device *); > + > +When the partner end enters or exits the modes, the port driver needs to notify > +the class with the following API: > + > +void typec_altmode_update_active(struct typec_altmode *alt, int mode, > + bool active); > diff --git a/MAINTAINERS b/MAINTAINERS > index e1b090f..0db33fb 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -11983,6 +11983,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.txt > +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 8689dcb..f42a3d3 100644 > --- a/drivers/usb/Kconfig > +++ b/drivers/usb/Kconfig > @@ -150,6 +150,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 && USB_COMMON && LEDS_TRIGGERS > diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile > index dca7856..51e381e 100644 > --- a/drivers/usb/Makefile > +++ b/drivers/usb/Makefile > @@ -61,3 +61,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 0000000..b229fb9 > --- /dev/null > +++ b/drivers/usb/typec/Kconfig > @@ -0,0 +1,7 @@ > + > +menu "USB PD and Type-C drivers" USB PD is independent of Type C right? Why club them together here? > + > +config TYPEC No help description? > + tristate > + > +endmenu > diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile > new file mode 100644 > index 0000000..1012a8b > --- /dev/null > +++ b/drivers/usb/typec/Makefile > @@ -0,0 +1 @@ > +obj-$(CONFIG_TYPEC) += typec.o <snip> I'll review the code a bit later. cheers, -roger ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-23 11:53 ` Roger Quadros @ 2016-06-23 13:08 ` Heikki Krogerus 0 siblings, 0 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-23 13:08 UTC (permalink / raw) To: Roger Quadros Cc: Greg KH, Guenter Roeck, Oliver Neukum, Felipe Balbi, linux-kernel, linux-usb Hi Roger, I'll fix all the typos you mention below... On Thu, Jun 23, 2016 at 02:53:11PM +0300, Roger Quadros wrote: > Hi Heikki, > > On 21/06/16 17:51, Heikki Krogerus wrote: > > 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 USB PD is > > s/PD/PD (Power Delivery) > > > available, also control over power role swapping and > > Alternate Modes. > > > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > --- > > Documentation/ABI/testing/sysfs-class-typec | 163 ++++ > > Documentation/usb/typec.txt | 101 +++ > > 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 | 1173 +++++++++++++++++++++++++++ > > include/linux/usb/typec.h | 255 ++++++ > > 9 files changed, 1713 insertions(+) > > create mode 100644 Documentation/ABI/testing/sysfs-class-typec > > create mode 100644 Documentation/usb/typec.txt > > 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 0000000..ce577f3 > > --- /dev/null > > +++ b/Documentation/ABI/testing/sysfs-class-typec > > @@ -0,0 +1,163 @@ > > +USB Type-C port devices (eg. /sys/class/typec/usbc0/) > > + > > +What: /sys/class/typec/<port>/current_data_role > > +Data: June 2016 > > s/Data/Date everywhere in this patch. > > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + The current USB data role the port is operating in. This > > + attribute can be used for requestion data role swapping on th > > s/requestion/requesting > > s/th/the > > > + port. > > Is it better to list all the values that can be here with a short note for each? > Same for all properties below? Sure. > Otherwise as a user I have no clue as to what all values I can set this to. > > > + > > +What: /sys/class/typec/<port>/current_power_role > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + The current power role, source or sink, of the port. This > > + attribute can be used to request power role swap on the port > > + when USB Power Delivery is available. > > So if it is not yet available, why add this now? s/...when USB Power Delivery is available/...when the port supports USB Power Delivery/ > > + > > +What: /sys/class/typec/<port>/current_vconn_role > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows the current VCONN role, source or sink, of the port. This > > + attribute can be used to request vconn role swap on the port > > s/vconn/VCONN > > > + when USB Power Delivery is available. > > Why add if not yet available? > > > + > > +What: /sys/class/typec/<port>/power_operation_mode > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows the current power power mode the port is in. Reads as on > > s/on/one > > > + of the following: > > + - USB - Normal power levels defined in USB specifications > > + - BC1.2 - Power levels defined in Battery Charging Specification > > + v1.2 > > + - USB Type-C 1.5A - Higher 1.5A current defined in USB Type-C > > + specification. > > + - USB Type-C 3.0A - Higher 3A current defined in USB Type-C > > + specification. > > + - USB Power Delivery - The voltages and currents defined in USB > > + Power Delivery specification > > What would it show when the port is disconnected? USB. That is the default. > Instead, is it somehow possible to list the actual negotiated current (in mA) > here or in some other property, if you want to know the mode as well? The current is not always going to be available for the port driver, and in any case out side the scope of the class. Those details are something that for example a USB Type-C PHY should always be able to detect, except BC1.2... I think I'm dropping that one. > > + > > +What: /sys/class/typec/<port>/preferred_role > > +Data: June 2016 > > +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. > > What would be the default setting? Default is no preference. I'll fix this. > > + > > +What: /sys/class/typec/<port>/supported_accessory_modes > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Lists the Accessory Modes, defined in the USB Type-C > > + specification, the port supports. > > + > > +What: /sys/class/typec/<port>/supported_data_roles > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Lists the USB data roles, host or device, the port is capable > > + of supporting. > > Can't it support both e.g in DRP case? Yes. s/host or device/host and device/ > > + > > +What: /sys/class/typec/<port>/supported_power_roles > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Lists the power roles, source and/or sink, the port is capable > > + of supporting. > > + > > +What: /sys/class/typec/<port>/supports_usb_power_delivery > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows if the port support USB Power Delivery. > > s/support/supports > > > + > > + > > +USB Type-C partner devices (eg. /sys/class/typec/usbc0-partner/) > > + > > +What: /sys/class/typec/<port>-partner/accessory > > <port>-partner/ or <port>/partner ? <port>-partner/. It is a device. > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows the name of the Accessory Mode if the partner attached to > > + the port is an accessory. Otherwise shows nothing. > > + > > +What: /sys/class/typec/<port>-partner/type > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows the type of the partner. Can be one of the following: > > + - USB - When the partner is normal USB host/peripheral. > > + - Charger - When the partner has been identified as dedicated > > + charger. > > + - Alternate Mode - When the partner supports Alternate Modes. > > + - Accessory - When the partner is one of the accessories with > > + specific Accessory Mode defined in USB Type-C > > + specification. > > + > > + > > +USB Type-C cable devices (eg. /sys/class/typec/usbc0-cable/) > > + > > +Note: The two cable plugs will have their own devices presenting when available > > I didn't get this part. How come two cable plugs can have 2 devices? One plug has one struct device? A cable has two plugs. > presenting what? The plug? On active cables the plugs may have alternate modes. > > +(eg. /sys/class/typec/usbc0-plug0). Both plugs may have their own active > > +alternate modes as described in USB Type-C and USB Power Delivery > > +specifications. > > + > > +What: /sys/class/typec/<port>-cable/active > > <port>-cable/ or <port>/cable ? <port>-cable/ > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows if the cable is active or passive. Only active cables can > > + have configurable alternate modes, therefore only active cables > > + will have plug devices. > > + > > +What: /sys/class/typec/<port>-cable/plug_type > > +Data: June 2016 > > +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 - USB Type-C > > + Captive - Non-standard > > + > > + > > +Alternate Mode devices (For example, > > +/sys/class/typec/usbc0-partner/usbc0-partner.svid:xxxx/) > > Why should it show usbc0-partner twice? Because device names need to be unique. > > + > > +What: /sys/class/typec/<dev>/<dev>.svid:<svid>/<mode>/active > > +Data: June 2016 > > +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. > > + > > +What: /sys/class/typec/<dev>/<dev>.svid:<svid>/<mode>/description > > +Data: June 2016 > > +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/<dev>/<dev>.svid:<svid>/<mode>/vdo > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows the VDO in hexadecimal returned from the Discover Modes > > + command. > > + > > +What: /sys/class/typec/<port>/<port>.svid:<svid>/<mode>/supported_roles > > +Data: June 2016 > > +Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> > > +Description: > > + Shows the roles, source or sink, the mode is supported with. > > + > > + 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. > > diff --git a/Documentation/usb/typec.txt b/Documentation/usb/typec.txt > > new file mode 100644 > > index 0000000..ddeda97 > > --- /dev/null > > +++ b/Documentation/usb/typec.txt > > @@ -0,0 +1,101 @@ > > +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 > > +expect the user space interface implementation in hope that it can be utilized > > s/expect/except/ > > > +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 offers the user space control > > +over the roles and alternate modes they support 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. > > + > > + > > +Interface > > +--------- > > +Every port will be presented as its own device under /sys/class/typec/. The > > +first port will be named "usbc0", the second "usbc1" and so on. > > We already know it is typec since it sits in /sys/class/typec > > Why not just call the instances "0", "1" and so on? A device named "0" or "1"... I wonder why other sub-systems are not naming their devices like that :-) > > + > > +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. The > > +partner attached to port "usbc0" will be named "usbc0-partner". > > Can the partner exist without the port? If not the partner should be located within > the port directory. It can't and won't exist without port, and the actual device does exist in the port directory. However, from the classes point of view that is irrelevant. A class will always create a link to its own group for all the devices attached to it. > > + > > +The cable and the two plugs on it may also be optionally be presented as their > > +own devices under /sys/class/typec/. The cable attached to the port "usbc0" port > > +will be named usbc0-cable and the plug on the SOP Prime end (see USB Power > > +Delivery Specification ch. 2.4) will be named "usbc-plug0" and on the SOP Double > > +Prime end "usbc0-plug1". > > If cables and plugs can't exist without the port they must come up within the port > directory. The same. > > + > > +If the port, partner or cable plug support Alternate Modes, every Alternate Mode > > +SVID will have their own device describing them. The Alternate Modes will not be > > +attached to the typec class. For the port's "usbc0" partner, the Alternate Modes > > +would have devices presented under /sys/class/typec/usbc0-partner/. Every mode > > +that is supported will have its own group under the Alternate Mode device named > > +"mode<id>". For example /sys/class/typec/usbc0/usbc0.svid:xxxx/mode0/. The > > +requests for entering/exiting the modes happens with the "active" attribute in > > +that group. > > + > > + > > +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: > > + > > +struct typec_port *typec_register_port(struct device *dev, > > + const struct typec_capability *cap); > > + > > +The class will provide handle to struct typec_port on success and ERR_PTR on > > +failure. The un-registration of the port happens with the following API: > > + > > +void typec_unregister_port(struct typec_port *port); > > + > > + > > +* Notifications > > + > > +When connection happens on a port, the port driver fills struct typec_connection > > +which is passed to the class. The class provides the following API for reporting > > +connection/disconnection: > > + > > +int typec_connect(struct typec_port *port, struct typec_connection *); > > +void typec_disconnect(struct typec_port *); > > + > > +When the partner end has executed a role change, the port driver uses the > > +following APIs to report it to the class: > > + > > +void typec_set_data_role(struct typec_port *, enum typec_data_role); > > +void typec_set_pwr_role(struct typec_port *, enum typec_role); > > +void typec_set_vconn_role(struct typec_port *, enum typec_role); > > +void typec_set_pwr_opmode(struct typec_port *, enum typec_pwr_opmode); > > + > > + > > +* Alternate Modes > > + > > +After connection, the port drivers register the alternate modes the partner > > +and/or cable plugs support. And before reporting disconnection, the port driver > > +_must_ unregister all the alternate modes registered for the partner and cable > > +plugs. The API takes the struct device of the partner or the cable plug as > > +parameter: > > + > > +int typec_register_altmodes(struct device *, struct typec_altmode *); > > +void typec_unregister_altmodes(struct device *); > > + > > +When the partner end enters or exits the modes, the port driver needs to notify > > +the class with the following API: > > + > > +void typec_altmode_update_active(struct typec_altmode *alt, int mode, > > + bool active); > > diff --git a/MAINTAINERS b/MAINTAINERS > > index e1b090f..0db33fb 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -11983,6 +11983,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.txt > > +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 8689dcb..f42a3d3 100644 > > --- a/drivers/usb/Kconfig > > +++ b/drivers/usb/Kconfig > > @@ -150,6 +150,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 && USB_COMMON && LEDS_TRIGGERS > > diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile > > index dca7856..51e381e 100644 > > --- a/drivers/usb/Makefile > > +++ b/drivers/usb/Makefile > > @@ -61,3 +61,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 0000000..b229fb9 > > --- /dev/null > > +++ b/drivers/usb/typec/Kconfig > > @@ -0,0 +1,7 @@ > > + > > +menu "USB PD and Type-C drivers" > > USB PD is independent of Type C right? Why club them together here? The are not tied to each other, that is for sure, but I don't think there will be that many drivers for USB PD controller or PHYs that would function without Type-C, so would separating them be that useful? > > + > > +config TYPEC > > No help description? Nope. Alone the class is useless, so I don't want to make it something that can be selected separately. And the port drivers will in any case depend on it so why bother the users. Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
[parent not found: <CAOiXhaKhPfY0Bz8TsZMFQsgLHZZ01DwZ=TPcXtH2nYvHx3PqVA@mail.gmail.com>]
[parent not found: <20160627095120.GC20801@kuha.fi.intel.com>]
[parent not found: <CAOiXhaJiche=jGbg_C2Jbmw1BnA5UYVNKOfhmy4CFiugoPV_+w@mail.gmail.com>]
* Re: [PATCHv3 1/2] usb: USB Type-C connector class [not found] ` <CAOiXhaJiche=jGbg_C2Jbmw1BnA5UYVNKOfhmy4CFiugoPV_+w@mail.gmail.com> @ 2016-06-27 12:13 ` Heikki Krogerus 2016-06-27 13:39 ` Guenter Roeck 2016-06-29 8:51 ` Rajaram R 0 siblings, 2 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-27 12:13 UTC (permalink / raw) To: Rajaram R; +Cc: linux-kernel, linux-usb, Oliver Neukum, Guenter Roeck Hi, On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: > May be I am missing user or usage of the driver.. I see this driver is > providing limited information of the Type-C connectors or the port > partner Yes, this interface can't provide directly information received from PD commands like Discover Identity. We will have to present the partners even when USB PD is not supported and in a consistent fashion. Some details will be available in any case indirectly. Like if there are modes, there will be devices presenting them, and the product type in case of partners will be the partner type. But there are a couple of attributes I have been thinking about adding for the partners: supported_data_roles supports_usb_power_delivery The supported data roles would respond bits 30 and 31 of the ID Header VDO. But when the partner does not support USB PD, we will have to report "unknown" in it. Oliver, Guenter! How do you guys feel about those? Is there any use for them? > On Mon, Jun 27, 2016 at 3:21 PM, Heikki Krogerus > <heikki.krogerus@linux.intel.com> wrote: > > On Fri, Jun 24, 2016 at 07:54:12PM +0530, Rajaram R wrote: > >> On Tue, Jun 21, 2016 at 8:21 PM, Heikki Krogerus > >> <heikki.krogerus@linux.intel.com> wrote: > >> > 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, > >> > >> Since we are defining this is as a unified interface for user space, > >> will the interface include identity details of local port and peer. > >> Or am I over looking something ? > > > > By peer, do you mean the partners? Sorry but could you elaborate the > > question? Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-27 12:13 ` Heikki Krogerus @ 2016-06-27 13:39 ` Guenter Roeck 2016-06-28 13:12 ` Heikki Krogerus 2016-06-29 8:51 ` Rajaram R 1 sibling, 1 reply; 34+ messages in thread From: Guenter Roeck @ 2016-06-27 13:39 UTC (permalink / raw) To: Heikki Krogerus, Rajaram R; +Cc: linux-kernel, linux-usb, Oliver Neukum On 06/27/2016 05:13 AM, Heikki Krogerus wrote: > Hi, > > On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: >> May be I am missing user or usage of the driver.. I see this driver is >> providing limited information of the Type-C connectors or the port >> partner > > Yes, this interface can't provide directly information received from > PD commands like Discover Identity. We will have to present the > partners even when USB PD is not supported and in a consistent > fashion. Some details will be available in any case indirectly. Like > if there are modes, there will be devices presenting them, and the > product type in case of partners will be the partner type. > > But there are a couple of attributes I have been thinking about adding > for the partners: > > supported_data_roles > supports_usb_power_delivery > > The supported data roles would respond bits 30 and 31 of the ID Header > VDO. But when the partner does not support USB PD, we will have to > report "unknown" in it. > Or make the attribute invisible in that case. > Oliver, Guenter! How do you guys feel about those? Is there any use > for them? > Definitely good for debugging and informational. On the top of my head, I don't immediately see what a user would do with it, though, but then it would not hurt either to have the information. I keep wondering if it would make sense to directly expose the ID header VDO, similar to the alternate mode VDOs, in the partner node. Guenter > >> On Mon, Jun 27, 2016 at 3:21 PM, Heikki Krogerus >> <heikki.krogerus@linux.intel.com> wrote: >>> On Fri, Jun 24, 2016 at 07:54:12PM +0530, Rajaram R wrote: >>>> On Tue, Jun 21, 2016 at 8:21 PM, Heikki Krogerus >>>> <heikki.krogerus@linux.intel.com> wrote: >>>>> 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, >>>> >>>> Since we are defining this is as a unified interface for user space, >>>> will the interface include identity details of local port and peer. >>>> Or am I over looking something ? >>> >>> By peer, do you mean the partners? Sorry but could you elaborate the >>> question? > > > Thanks, > ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-27 13:39 ` Guenter Roeck @ 2016-06-28 13:12 ` Heikki Krogerus 2016-06-28 13:28 ` Guenter Roeck 0 siblings, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-28 13:12 UTC (permalink / raw) To: Guenter Roeck; +Cc: Rajaram R, linux-kernel, linux-usb, Oliver Neukum On Mon, Jun 27, 2016 at 06:39:46AM -0700, Guenter Roeck wrote: > On 06/27/2016 05:13 AM, Heikki Krogerus wrote: > > Hi, > > > > On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: > > > May be I am missing user or usage of the driver.. I see this driver is > > > providing limited information of the Type-C connectors or the port > > > partner > > > > Yes, this interface can't provide directly information received from > > PD commands like Discover Identity. We will have to present the > > partners even when USB PD is not supported and in a consistent > > fashion. Some details will be available in any case indirectly. Like > > if there are modes, there will be devices presenting them, and the > > product type in case of partners will be the partner type. > > > > But there are a couple of attributes I have been thinking about adding > > for the partners: > > > > supported_data_roles > > supports_usb_power_delivery > > > > The supported data roles would respond bits 30 and 31 of the ID Header > > VDO. But when the partner does not support USB PD, we will have to > > report "unknown" in it. > > > > Or make the attribute invisible in that case. Well, why not. I did not like the idea of hiding an attribute previously. I preferred to have an attribute always available, unless there was a single and clear way to determine the cases where any of the attributes for example with our partners would be visible or not.. But who cares. > > Oliver, Guenter! How do you guys feel about those? Is there any use > > for them? > > > Definitely good for debugging and informational. On the top of my head, > I don't immediately see what a user would do with it, though, but then > it would not hurt either to have the information. > > I keep wondering if it would make sense to directly expose the ID header > VDO, similar to the alternate mode VDOs, in the partner node. Yes, it makes sense. I'll add an attribute for that. But since you proposed hiding the attributes, I'll add an attribute "supports_usb_power_deliver" in any case, and make the vdo attribute visible only if it returs 1. I'll also make the "accessory" attribute visible only in case the partner type is accessory. Thanks Guenter, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-28 13:12 ` Heikki Krogerus @ 2016-06-28 13:28 ` Guenter Roeck 0 siblings, 0 replies; 34+ messages in thread From: Guenter Roeck @ 2016-06-28 13:28 UTC (permalink / raw) To: Heikki Krogerus; +Cc: Rajaram R, linux-kernel, linux-usb, Oliver Neukum On 06/28/2016 06:12 AM, Heikki Krogerus wrote: > On Mon, Jun 27, 2016 at 06:39:46AM -0700, Guenter Roeck wrote: >> On 06/27/2016 05:13 AM, Heikki Krogerus wrote: >>> Hi, >>> >>> On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: >>>> May be I am missing user or usage of the driver.. I see this driver is >>>> providing limited information of the Type-C connectors or the port >>>> partner >>> >>> Yes, this interface can't provide directly information received from >>> PD commands like Discover Identity. We will have to present the >>> partners even when USB PD is not supported and in a consistent >>> fashion. Some details will be available in any case indirectly. Like >>> if there are modes, there will be devices presenting them, and the >>> product type in case of partners will be the partner type. >>> >>> But there are a couple of attributes I have been thinking about adding >>> for the partners: >>> >>> supported_data_roles >>> supports_usb_power_delivery >>> >>> The supported data roles would respond bits 30 and 31 of the ID Header >>> VDO. But when the partner does not support USB PD, we will have to >>> report "unknown" in it. >>> >> >> Or make the attribute invisible in that case. > > Well, why not. I did not like the idea of hiding an attribute > previously. I preferred to have an attribute always available, unless > there was a single and clear way to determine the cases where any of > the attributes for example with our partners would be visible or not.. > But who cares. > It would be visible if supports_usb_power_delivery is true. Doesn't that match your requirements ? >>> Oliver, Guenter! How do you guys feel about those? Is there any use >>> for them? >>> >> Definitely good for debugging and informational. On the top of my head, >> I don't immediately see what a user would do with it, though, but then >> it would not hurt either to have the information. >> >> I keep wondering if it would make sense to directly expose the ID header >> VDO, similar to the alternate mode VDOs, in the partner node. > > Yes, it makes sense. I'll add an attribute for that. > > But since you proposed hiding the attributes, I'll add an attribute > "supports_usb_power_deliver" in any case, and make the vdo attribute > visible only if it returs 1. I'll also make the "accessory" attribute > visible only in case the partner type is accessory. > Ok with me. Thanks, Guenter ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-27 12:13 ` Heikki Krogerus 2016-06-27 13:39 ` Guenter Roeck @ 2016-06-29 8:51 ` Rajaram R 2016-06-29 10:30 ` Heikki Krogerus 1 sibling, 1 reply; 34+ messages in thread From: Rajaram R @ 2016-06-29 8:51 UTC (permalink / raw) To: Heikki Krogerus; +Cc: linux-kernel, linux-usb, Oliver Neukum, Guenter Roeck On Mon, Jun 27, 2016 at 5:43 PM, Heikki Krogerus <heikki.krogerus@linux.intel.com> wrote: > Hi, > > On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: >> May be I am missing user or usage of the driver.. I see this driver is >> providing limited information of the Type-C connectors or the port >> partner > > Yes, this interface can't provide directly information received from > PD commands like Discover Identity. We will have to present the > partners even when USB PD is not supported and in a consistent > fashion. Some details will be available in any case indirectly. Like > if there are modes, there will be devices presenting them, and the > product type in case of partners will be the partner type. Agree. What is the end use of this driver? IMO end use case will decide what attributes to be shared. Since we are terming this as a universal representation for user space we may need to expose details such as Discovery details say Vendor ID, Product ID, Super Speed support etc which are not related to alt mode. In the legacy drivers complete descriptors of the device is available for user space to build applications. > > But there are a couple of attributes I have been thinking about adding > for the partners: > > supported_data_roles > supports_usb_power_delivery > > The supported data roles would respond bits 30 and 31 of the ID Header > VDO. But when the partner does not support USB PD, we will have to > report "unknown" in it. > > Oliver, Guenter! How do you guys feel about those? Is there any use > for them? > > >> On Mon, Jun 27, 2016 at 3:21 PM, Heikki Krogerus >> <heikki.krogerus@linux.intel.com> wrote: >> > On Fri, Jun 24, 2016 at 07:54:12PM +0530, Rajaram R wrote: >> >> On Tue, Jun 21, 2016 at 8:21 PM, Heikki Krogerus >> >> <heikki.krogerus@linux.intel.com> wrote: >> >> > 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, >> >> >> >> Since we are defining this is as a unified interface for user space, >> >> will the interface include identity details of local port and peer. >> >> Or am I over looking something ? >> > >> > By peer, do you mean the partners? Sorry but could you elaborate the >> > question? > > > Thanks, > > -- > heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-29 8:51 ` Rajaram R @ 2016-06-29 10:30 ` Heikki Krogerus 2016-06-29 10:51 ` Rajaram R 0 siblings, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-29 10:30 UTC (permalink / raw) To: Rajaram R; +Cc: linux-kernel, linux-usb, Oliver Neukum, Guenter Roeck On Wed, Jun 29, 2016 at 02:21:10PM +0530, Rajaram R wrote: > On Mon, Jun 27, 2016 at 5:43 PM, Heikki Krogerus > <heikki.krogerus@linux.intel.com> wrote: > > Hi, > > > > On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: > >> May be I am missing user or usage of the driver.. I see this driver is > >> providing limited information of the Type-C connectors or the port > >> partner > > > > Yes, this interface can't provide directly information received from > > PD commands like Discover Identity. We will have to present the > > partners even when USB PD is not supported and in a consistent > > fashion. Some details will be available in any case indirectly. Like > > if there are modes, there will be devices presenting them, and the > > product type in case of partners will be the partner type. > > Agree. What is the end use of this driver? IMO end use case will > decide what attributes to be shared. Since we are terming this as a > universal representation for user space we may need to expose details > such as Discovery details say Vendor ID, Product ID, Super Speed > support etc which are not related to alt mode. In the legacy drivers > complete descriptors of the device is available for user space to > build applications. The details about the USB connection are out side the scope the this class, and in most cases the port driver will not even have them at their disposal. We can determine that the connector is in USB mode, and that's about it. But those details will in any case be exposed by the USB subsystem, so why should we duplicate them? The user space has been so far relying on getting the details from the normal interfaces the USB subsystem provides and that should not change. Thanks, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-29 10:30 ` Heikki Krogerus @ 2016-06-29 10:51 ` Rajaram R 2016-06-29 11:27 ` Heikki Krogerus 0 siblings, 1 reply; 34+ messages in thread From: Rajaram R @ 2016-06-29 10:51 UTC (permalink / raw) To: Heikki Krogerus; +Cc: linux-kernel, linux-usb, Oliver Neukum, Guenter Roeck On Wed, Jun 29, 2016 at 4:00 PM, Heikki Krogerus <heikki.krogerus@linux.intel.com> wrote: > On Wed, Jun 29, 2016 at 02:21:10PM +0530, Rajaram R wrote: >> On Mon, Jun 27, 2016 at 5:43 PM, Heikki Krogerus >> <heikki.krogerus@linux.intel.com> wrote: >> > Hi, >> > >> > On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: >> >> May be I am missing user or usage of the driver.. I see this driver is >> >> providing limited information of the Type-C connectors or the port >> >> partner >> > >> > Yes, this interface can't provide directly information received from >> > PD commands like Discover Identity. We will have to present the >> > partners even when USB PD is not supported and in a consistent >> > fashion. Some details will be available in any case indirectly. Like >> > if there are modes, there will be devices presenting them, and the >> > product type in case of partners will be the partner type. >> >> Agree. What is the end use of this driver? IMO end use case will >> decide what attributes to be shared. Since we are terming this as a >> universal representation for user space we may need to expose details >> such as Discovery details say Vendor ID, Product ID, Super Speed >> support etc which are not related to alt mode. In the legacy drivers >> complete descriptors of the device is available for user space to >> build applications. > > The details about the USB connection are out side the scope the this > class, and in most cases the port driver will not even have them at > their disposal. We can determine that the connector is in USB mode, > and that's about it. > > But those details will in any case be exposed by the USB subsystem, so > why should we duplicate them? The user space has been so far relying > on getting the details from the normal interfaces the USB subsystem > provides and that should not change. Apologize for bringing in USB example. I used it to as an example to say that complete device details are exposed to user space by other drivers. Sticking to the current topic/context more details of Type-C port/partner, a detailed information(with restrictions) will help build more user applications. > > > Thanks, > > -- > heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-29 10:51 ` Rajaram R @ 2016-06-29 11:27 ` Heikki Krogerus 2016-07-04 8:55 ` Oliver Neukum 0 siblings, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-29 11:27 UTC (permalink / raw) To: Rajaram R, Oliver Neukum; +Cc: linux-kernel, linux-usb, Guenter Roeck On Wed, Jun 29, 2016 at 04:21:49PM +0530, Rajaram R wrote: > On Wed, Jun 29, 2016 at 4:00 PM, Heikki Krogerus > <heikki.krogerus@linux.intel.com> wrote: > > On Wed, Jun 29, 2016 at 02:21:10PM +0530, Rajaram R wrote: > >> On Mon, Jun 27, 2016 at 5:43 PM, Heikki Krogerus > >> <heikki.krogerus@linux.intel.com> wrote: > >> > Hi, > >> > > >> > On Mon, Jun 27, 2016 at 03:51:08PM +0530, Rajaram R wrote: > >> >> May be I am missing user or usage of the driver.. I see this driver is > >> >> providing limited information of the Type-C connectors or the port > >> >> partner > >> > > >> > Yes, this interface can't provide directly information received from > >> > PD commands like Discover Identity. We will have to present the > >> > partners even when USB PD is not supported and in a consistent > >> > fashion. Some details will be available in any case indirectly. Like > >> > if there are modes, there will be devices presenting them, and the > >> > product type in case of partners will be the partner type. > >> > >> Agree. What is the end use of this driver? IMO end use case will > >> decide what attributes to be shared. Since we are terming this as a > >> universal representation for user space we may need to expose details > >> such as Discovery details say Vendor ID, Product ID, Super Speed > >> support etc which are not related to alt mode. In the legacy drivers > >> complete descriptors of the device is available for user space to > >> build applications. > > > > The details about the USB connection are out side the scope the this > > class, and in most cases the port driver will not even have them at > > their disposal. We can determine that the connector is in USB mode, > > and that's about it. > > > > But those details will in any case be exposed by the USB subsystem, so > > why should we duplicate them? The user space has been so far relying > > on getting the details from the normal interfaces the USB subsystem > > provides and that should not change. > > Apologize for bringing in USB example. I used it to as an example to > say that complete device details are exposed to user space by other > drivers. > > Sticking to the current topic/context more details of Type-C > port/partner, a detailed information(with restrictions) will help > build more user applications. IMO we are exposing more or less all relevant information about the ports that the USB Type-C specification defines. And for control we should also be providing mechanisms for all that the spec. defines, so mainly role swapping, and entering/exiting the altenate modes. If there is something missing, please point it out. Otherwise, I think we are providing everything we can. About the end user of the interface, I think Oliver knows more about that. But I would imagine that the use cases will be something like, for example, on systems that need prefer sertain roles, perhaps Host for example on some server systems, need to have something like a udev script to set the preferred role and/or attempt role swap if the other role (device) is initially given to a port after connection. Br, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 1/2] usb: USB Type-C connector class 2016-06-29 11:27 ` Heikki Krogerus @ 2016-07-04 8:55 ` Oliver Neukum 0 siblings, 0 replies; 34+ messages in thread From: Oliver Neukum @ 2016-07-04 8:55 UTC (permalink / raw) To: Heikki Krogerus; +Cc: Rajaram R, Guenter Roeck, linux-kernel, linux-usb On Wed, 2016-06-29 at 14:27 +0300, Heikki Krogerus wrote: > About the end user of the interface, I think Oliver knows more about > that. But I would imagine that the use cases will be something like, > for example, on systems that need prefer sertain roles, perhaps Host > for example on some server systems, need to have something like a udev > script to set the preferred role and/or attempt role swap if the other > role (device) is initially given to a port after connection. And I would say again that try.SRC and try.SNK need a module parameter as a later reversal needs a virtual disconnect. Regards Oliver ^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCHv3 2/2] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY 2016-06-21 14:51 [PATCHv3 0/2] USB Type-C Connector class Heikki Krogerus 2016-06-21 14:51 ` [PATCHv3 1/2] usb: USB Type-C connector class Heikki Krogerus @ 2016-06-21 14:51 ` Heikki Krogerus 2016-06-21 22:25 ` [PATCHv3 0/2] USB Type-C Connector class Guenter Roeck 2 siblings, 0 replies; 34+ messages in thread From: Heikki Krogerus @ 2016-06-21 14:51 UTC (permalink / raw) To: Greg KH, Guenter Roeck, Oliver Neukum Cc: Felipe Balbi, 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> --- drivers/usb/typec/Kconfig | 14 ++ drivers/usb/typec/Makefile | 1 + drivers/usb/typec/typec_wcove.c | 376 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 391 insertions(+) create mode 100644 drivers/usb/typec/typec_wcove.c diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index b229fb9..7a345a4 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -4,4 +4,18 @@ menu "USB PD 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 + 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 1012a8b..b9cb862 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 0000000..4309ac6 --- /dev/null +++ b/drivers/usb/typec/typec_wcove.c @@ -0,0 +1,376 @@ +/** + * typec_wcove.c - WhiskeyCove PMIC USB Type-C PHY driver + * + * Copyright (C) 2016 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 completion complete; + struct typec_capability cap; + struct typec_connection con; + 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 void wcove_typec_device_mode(struct wcove_typec *wcove) +{ + wcove->partner.type = TYPEC_PARTNER_USB; + wcove->con.partner = &wcove->partner; + wcove->con.pwr_role = TYPEC_SINK; + wcove->con.vconn_role = TYPEC_SINK; + wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_DEVICE); + typec_connect(wcove->port, &wcove->con); +} + +static irqreturn_t wcove_typec_irq(int irq, void *data) +{ + 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"); + regmap_write(wcove->regmap, USBC_IRQ1, cc_irq1); + } + + if (cc_irq2) { + regmap_write(wcove->regmap, USBC_IRQ2, cc_irq2); + /* + * Ingoring any PD communication interrupts until the PD stack + * is in place + */ + 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->con.partner) { + typec_disconnect(wcove->port); + memset(&wcove->con, 0, sizeof(wcove->con)); + memset(&wcove->partner, 0, sizeof(wcove->partner)); + } + + wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION, + WCOVE_ORIENTATION_NORMAL); + /* Host mode by default */ + wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_HOST); + goto out; + } + + if (wcove->con.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; + } + + switch (USBC_STATUS1_RSLT(status1)) { + case USBC_RSLT_SRC_DEFAULT: + wcove->con.pwr_opmode = TYPEC_PWR_MODE_USB; + wcove_typec_device_mode(wcove); + break; + case USBC_RSLT_SRC_1_5A: + wcove->con.pwr_opmode = TYPEC_PWR_MODE_1_5A; + wcove_typec_device_mode(wcove); + break; + case USBC_RSLT_SRC_3_0A: + wcove->con.pwr_opmode = TYPEC_PWR_MODE_3_0A; + wcove_typec_device_mode(wcove); + break; + case USBC_RSLT_SNK: + wcove->partner.type = TYPEC_PARTNER_USB; + wcove->con.partner = &wcove->partner; + wcove->con.data_role = TYPEC_HOST; + wcove->con.pwr_role = TYPEC_SOURCE; + wcove->con.vconn_role = TYPEC_SOURCE; + wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_HOST); + typec_connect(wcove->port, &wcove->con); + break; + case USBC_RSLT_DEBUG_ACC: + wcove->partner.accessory = TYPEC_ACCESSORY_DEBUG; + wcove->partner.type = TYPEC_PARTNER_ACCESSORY; + wcove->con.partner = &wcove->partner; + typec_connect(wcove->port, &wcove->con); + break; + case USBC_RSLT_AUDIO_ACC: + wcove->partner.accessory = TYPEC_ACCESSORY_AUDIO; + wcove->partner.type = TYPEC_PARTNER_ACCESSORY; + wcove->con.partner = &wcove->partner; + typec_connect(wcove->port, &wcove->con); + break; + default: + dev_WARN(wcove->dev, "%s Undefined result\n", __func__); + goto err; + } + + if (!completion_done(&wcove->complete)) + complete(&wcove->complete); +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; + + init_completion(&wcove->complete); + 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; + + wcove->cap.type = TYPEC_PORT_DRP; + + wcove->port = typec_register_port(&pdev->dev, &wcove->cap); + if (IS_ERR(wcove->port)) + return PTR_ERR(wcove->port); + + if (!acpi_check_dsm(ACPI_HANDLE(&pdev->dev), uuid.b, 0, 0x1f)) { + dev_err(&pdev->dev, "Missing _DSM functions\n"); + return -ENODEV; + } + + /* Make sure the PD PHY is disabled until PD stack is ready */ + 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)); + + /* 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_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"); -- 2.8.1 ^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCHv3 0/2] USB Type-C Connector class 2016-06-21 14:51 [PATCHv3 0/2] USB Type-C Connector class Heikki Krogerus 2016-06-21 14:51 ` [PATCHv3 1/2] usb: USB Type-C connector class Heikki Krogerus 2016-06-21 14:51 ` [PATCHv3 2/2] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY Heikki Krogerus @ 2016-06-21 22:25 ` Guenter Roeck 2016-06-22 9:51 ` Heikki Krogerus 2 siblings, 1 reply; 34+ messages in thread From: Guenter Roeck @ 2016-06-21 22:25 UTC (permalink / raw) To: Heikki Krogerus Cc: Greg KH, Oliver Neukum, Felipe Balbi, linux-kernel, linux-usb On Tue, Jun 21, 2016 at 05:51:49PM +0300, Heikki Krogerus wrote: > Hi, > > I'm considering all the RFCs I send after v1 as v2 (I don't remember > how many I send). Hope this is OK and hope there is nothing big > missing anymore (or broken). > > Sorry about the delay. I've been really busy with some internal tasks. > I'm guessing we missed v4.8 with this thing. I'm sorry about that. > > I'm including in this series a driver for the Broxton PMIC USB Type-C > PHY. > Can you by any chance push the current version into your repository on github ? Thanks, Guenter > > 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 (2): > 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 | 163 ++++ > Documentation/usb/typec.txt | 101 +++ > MAINTAINERS | 9 + > drivers/usb/Kconfig | 2 + > drivers/usb/Makefile | 2 + > drivers/usb/typec/Kconfig | 21 + > drivers/usb/typec/Makefile | 2 + > drivers/usb/typec/typec.c | 1173 +++++++++++++++++++++++++++ > drivers/usb/typec/typec_wcove.c | 376 +++++++++ > include/linux/usb/typec.h | 255 ++++++ > 10 files changed, 2104 insertions(+) > create mode 100644 Documentation/ABI/testing/sysfs-class-typec > create mode 100644 Documentation/usb/typec.txt > 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.8.1 > ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 0/2] USB Type-C Connector class 2016-06-21 22:25 ` [PATCHv3 0/2] USB Type-C Connector class Guenter Roeck @ 2016-06-22 9:51 ` Heikki Krogerus 2016-06-22 13:24 ` Guenter Roeck 0 siblings, 1 reply; 34+ messages in thread From: Heikki Krogerus @ 2016-06-22 9:51 UTC (permalink / raw) To: Guenter Roeck Cc: Greg KH, Oliver Neukum, Felipe Balbi, linux-kernel, linux-usb Hi Guenter, On Tue, Jun 21, 2016 at 03:25:55PM -0700, Guenter Roeck wrote: > On Tue, Jun 21, 2016 at 05:51:49PM +0300, Heikki Krogerus wrote: > > Hi, > > > > I'm considering all the RFCs I send after v1 as v2 (I don't remember > > how many I send). Hope this is OK and hope there is nothing big > > missing anymore (or broken). > > > > Sorry about the delay. I've been really busy with some internal tasks. > > I'm guessing we missed v4.8 with this thing. I'm sorry about that. > > > > I'm including in this series a driver for the Broxton PMIC USB Type-C > > PHY. > > > Can you by any chance push the current version into your repository > on github ? Sure, but Felipe has also put these patches to a branch testing/typec in his tree: https://git.kernel.org/cgit/linux/kernel/git/balbi/usb.git/log/?h=testing/typec Cheers, -- heikki ^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCHv3 0/2] USB Type-C Connector class 2016-06-22 9:51 ` Heikki Krogerus @ 2016-06-22 13:24 ` Guenter Roeck 0 siblings, 0 replies; 34+ messages in thread From: Guenter Roeck @ 2016-06-22 13:24 UTC (permalink / raw) To: Heikki Krogerus Cc: Greg KH, Oliver Neukum, Felipe Balbi, linux-kernel, linux-usb On 06/22/2016 02:51 AM, Heikki Krogerus wrote: > Hi Guenter, > > On Tue, Jun 21, 2016 at 03:25:55PM -0700, Guenter Roeck wrote: >> On Tue, Jun 21, 2016 at 05:51:49PM +0300, Heikki Krogerus wrote: >>> Hi, >>> >>> I'm considering all the RFCs I send after v1 as v2 (I don't remember >>> how many I send). Hope this is OK and hope there is nothing big >>> missing anymore (or broken). >>> >>> Sorry about the delay. I've been really busy with some internal tasks. >>> I'm guessing we missed v4.8 with this thing. I'm sorry about that. >>> >>> I'm including in this series a driver for the Broxton PMIC USB Type-C >>> PHY. >>> >> Can you by any chance push the current version into your repository >> on github ? > > Sure, but Felipe has also put these patches to a branch testing/typec > in his tree: > https://git.kernel.org/cgit/linux/kernel/git/balbi/usb.git/log/?h=testing/typec > That works just as well, of course. Thanks, Guenter ^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2016-07-04 8:59 UTC | newest] Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-06-21 14:51 [PATCHv3 0/2] USB Type-C Connector class Heikki Krogerus 2016-06-21 14:51 ` [PATCHv3 1/2] usb: USB Type-C connector class Heikki Krogerus 2016-06-21 20:25 ` Oliver Neukum 2016-06-22 9:50 ` Heikki Krogerus 2016-06-22 10:03 ` Heikki Krogerus 2016-06-22 10:21 ` Oliver Neukum 2016-06-22 10:14 ` Oliver Neukum 2016-06-22 11:44 ` Heikki Krogerus 2016-06-22 13:47 ` Oliver Neukum 2016-06-22 14:38 ` Heikki Krogerus 2016-06-22 16:44 ` Oliver Neukum 2016-06-23 8:23 ` Heikki Krogerus 2016-06-23 8:38 ` Oliver Neukum 2016-06-23 12:00 ` Heikki Krogerus 2016-06-23 12:25 ` Roger Quadros 2016-06-23 13:11 ` Heikki Krogerus 2016-06-23 13:29 ` Guenter Roeck 2016-06-22 21:54 ` Guenter Roeck 2016-06-23 8:25 ` Heikki Krogerus 2016-06-23 11:53 ` Roger Quadros 2016-06-23 13:08 ` Heikki Krogerus [not found] ` <CAOiXhaKhPfY0Bz8TsZMFQsgLHZZ01DwZ=TPcXtH2nYvHx3PqVA@mail.gmail.com> [not found] ` <20160627095120.GC20801@kuha.fi.intel.com> [not found] ` <CAOiXhaJiche=jGbg_C2Jbmw1BnA5UYVNKOfhmy4CFiugoPV_+w@mail.gmail.com> 2016-06-27 12:13 ` Heikki Krogerus 2016-06-27 13:39 ` Guenter Roeck 2016-06-28 13:12 ` Heikki Krogerus 2016-06-28 13:28 ` Guenter Roeck 2016-06-29 8:51 ` Rajaram R 2016-06-29 10:30 ` Heikki Krogerus 2016-06-29 10:51 ` Rajaram R 2016-06-29 11:27 ` Heikki Krogerus 2016-07-04 8:55 ` Oliver Neukum 2016-06-21 14:51 ` [PATCHv3 2/2] usb: typec: add driver for Intel Whiskey Cove PMIC USB Type-C PHY Heikki Krogerus 2016-06-21 22:25 ` [PATCHv3 0/2] USB Type-C Connector class Guenter Roeck 2016-06-22 9:51 ` Heikki Krogerus 2016-06-22 13:24 ` Guenter Roeck
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).