All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
To: Greg KH <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	Mathias Nyman <mathias.nyman@linux.intel.com>,
	Felipe Balbi <balbi@kernel.org>
Subject: [PATCH 2/3] usb: type-c: USB Type-C Connector System Software Interface
Date: Tue,  9 Feb 2016 19:01:22 +0200	[thread overview]
Message-ID: <1455037283-106479-3-git-send-email-heikki.krogerus@linux.intel.com> (raw)
In-Reply-To: <1455037283-106479-1-git-send-email-heikki.krogerus@linux.intel.com>

USB Type-C Connector System Software Interface (UCSI) is a
specification that defines registers and data structures
used to interface with the USB Type-C connectors on a system.

The specification is public and available at:
http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
 drivers/usb/type-c/Kconfig  |   8 +
 drivers/usb/type-c/Makefile |   1 +
 drivers/usb/type-c/ucsi.c   | 450 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/type-c/ucsi.h   | 219 +++++++++++++++++++++
 4 files changed, 678 insertions(+)
 create mode 100644 drivers/usb/type-c/ucsi.c
 create mode 100644 drivers/usb/type-c/ucsi.h

diff --git a/drivers/usb/type-c/Kconfig b/drivers/usb/type-c/Kconfig
index b229fb9..02abd74 100644
--- a/drivers/usb/type-c/Kconfig
+++ b/drivers/usb/type-c/Kconfig
@@ -4,4 +4,12 @@ menu "USB PD and Type-C drivers"
 config TYPEC
 	tristate
 
+config TYPEC_UCSI
+	tristate "USB Type-C Connector System Software Interface"
+	select TYPEC
+	help
+	  USB Type-C Connector System Software Interface (UCSI) describes the
+	  registers and data structures used to interface with the USB Type-C
+	  connectors on a system.
+
 endmenu
diff --git a/drivers/usb/type-c/Makefile b/drivers/usb/type-c/Makefile
index 1012a8b..ab974ba 100644
--- a/drivers/usb/type-c/Makefile
+++ b/drivers/usb/type-c/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_TYPEC)		+= typec.o
+obj-$(CONFIG_TYPEC_UCSI)	+= ucsi.o
diff --git a/drivers/usb/type-c/ucsi.c b/drivers/usb/type-c/ucsi.c
new file mode 100644
index 0000000..0107a85
--- /dev/null
+++ b/drivers/usb/type-c/ucsi.c
@@ -0,0 +1,450 @@
+/*
+ * ucsi.c - USB Type-C Connector System Software Interface
+ *
+ * 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/completion.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb/typec.h>
+
+#include "ucsi.h"
+
+#define UCSI_ERROR 1
+#define UCSI_BUSY 2
+
+#define to_ucsi_connector(_port_) container_of(_port_->cap,                    \
+					       struct ucsi_connector,          \
+					       typec_cap)
+
+#define cci_to_connector(_ucsi_, cci) (_ucsi_->connector +		       \
+					UCSI_CCI_CONNECTOR_CHANGE(cci) - 1)
+
+struct ucsi_connector {
+	unsigned num;
+	struct ucsi *ucsi;
+	struct work_struct work;
+	struct typec_port *port;
+	struct typec_capability typec_cap;
+	struct ucsi_connector_capability cap;
+};
+
+struct ucsi {
+	struct device *dev;
+	struct ucsi_ppm *ppm;
+
+	int status;
+	struct completion complete;
+	struct ucsi_capability cap;
+	struct ucsi_connector *connector;
+};
+
+static int ucsi_ack(struct ucsi *ucsi, u8 cmd)
+{
+	struct ucsi_control *ctrl = (void *)&ucsi->ppm->data->control;
+	int ret;
+
+	ucsi->ppm->data->control = 0;
+	ctrl->cmd = UCSI_ACK_CC_CI;
+	ctrl->data = cmd;
+
+	ret = ucsi->ppm->cmd(ucsi->ppm);
+	if (ret)
+		return ret;
+
+	/* Waiting for ACK also with ACK CMD for now */
+	wait_for_completion(&ucsi->complete);
+	return 0;
+}
+
+static int ucsi_run_cmd(struct ucsi *ucsi, void *data, size_t size)
+{
+	int status;
+	int ret;
+
+	dev_vdbg(ucsi->dev, "%s control 0x%llx\n", __func__,
+		 ucsi->ppm->data->control);
+
+	ret = ucsi->ppm->cmd(ucsi->ppm);
+	if (ret)
+		return ret;
+
+	/* REVISIT: We may need to set UCSI_CCI_CMD_COMPLETE flag here */
+	wait_for_completion(&ucsi->complete);
+
+	status = ucsi->status;
+	if (status != UCSI_ERROR && size)
+		memcpy(data, ucsi->ppm->data->message_in, size);
+
+	ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
+	if (ret)
+		goto out;
+
+	if (status == UCSI_ERROR) {
+		u16 error;
+
+		ucsi->ppm->data->control = UCSI_GET_ERROR_STATUS;
+		ret = ucsi->ppm->cmd(ucsi->ppm);
+		if (ret)
+			goto out;
+
+		wait_for_completion(&ucsi->complete);
+
+		/* Something has really gone wrong */
+		if (ucsi->status == UCSI_ERROR) {
+			ret = -ENODEV;
+			goto out;
+		}
+
+		memcpy(&error, ucsi->ppm->data->message_in, sizeof(error));
+
+		ret = ucsi_ack(ucsi, UCSI_ACK_CMD);
+		if (ret)
+			goto out;
+
+		switch (error) {
+		case UCSI_ERROR_INVALID_CON_NUM:
+			ret = -ENXIO;
+			break;
+		case UCSI_ERROR_INCOMPATIBLE_PARTNER:
+		case UCSI_ERROR_CC_COMMUNICATION_ERR:
+		case UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL:
+			ret = -EIO;
+			break;
+		case UCSI_ERROR_DEAD_BATTERY:
+			dev_warn(ucsi->dev, "Dead Battery Condition!\n");
+			ret = -EPERM;
+			break;
+		case UCSI_ERROR_UNREGONIZED_CMD:
+		case UCSI_ERROR_INVALID_CMD_ARGUMENT:
+		default:
+			ret = -EINVAL;
+			break;
+		}
+	}
+out:
+	ucsi->ppm->data->control = 0;
+	return ret;
+}
+
+static int ucsi_dr_swap(struct typec_port *port)
+{
+	struct ucsi_connector *con = to_ucsi_connector(port);
+	struct ucsi_uor_cmd *ctrl = (void *)&con->ucsi->ppm->data->control;
+
+	ctrl->cmd = UCSI_SET_UOR;
+	ctrl->con_num = con->num;
+	ctrl->role = port->data_role == TYPEC_HOST ?
+			UCSI_UOR_ROLE_UFP : UCSI_UOR_ROLE_DFP;
+	if (port->cap->type == TYPEC_PORT_DRP)
+		ctrl->role |= UCSI_UOR_ROLE_DRP;
+
+	return ucsi_run_cmd(con->ucsi, NULL, 0);
+}
+
+static int ucsi_pr_swap(struct typec_port *port)
+{
+	struct ucsi_connector *con = to_ucsi_connector(port);
+	struct ucsi_uor_cmd *ctrl = (void *)&con->ucsi->ppm->data->control;
+
+	/* The command structure is identical to SET_UOR command structure */
+	ctrl->cmd = UCSI_SET_PDR;
+	ctrl->con_num = con->num;
+	ctrl->role = port->pwr_role == TYPEC_PWR_SOURCE ?
+			UCSI_UOR_ROLE_UFP : UCSI_UOR_ROLE_DFP;
+	/* Always accepting power swap requests from partner for now */
+	ctrl->role |= UCSI_UOR_ROLE_DRP;
+
+	return ucsi_run_cmd(con->ucsi, NULL, 0);
+}
+
+static int ucsi_get_constat(struct ucsi_connector *con,
+			    struct ucsi_connector_status *constat)
+{
+	struct ucsi_control *ctrl = (void *)&con->ucsi->ppm->data->control;
+
+	ctrl->cmd = UCSI_GET_CONNECTOR_STATUS;
+	ctrl->data = con->num;
+
+	return ucsi_run_cmd(con->ucsi, constat, sizeof(*constat));
+}
+
+static int
+ucsi_connect(struct ucsi_connector *con, struct ucsi_connector_status *constat)
+{
+	struct typec_port *port = con->port;
+
+	port->connected = true;
+
+	if (constat->partner_flags & UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE)
+		port->partner_type = TYPEC_PARTNER_ALTMODE;
+	else
+		port->partner_type = TYPEC_PARTNER_USB;
+
+	switch (constat->partner_type) {
+	case UCSI_CONSTAT_PARTNER_TYPE_CABLE_NO_UFP:
+		/* REVISIT: We don't care about just the cable for now */
+		return 0;
+	case UCSI_CONSTAT_PARTNER_TYPE_DFP:
+	case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
+		port->pwr_role = TYPEC_PWR_SINK;
+		port->data_role = TYPEC_DEVICE;
+		break;
+	case UCSI_CONSTAT_PARTNER_TYPE_UFP:
+		port->pwr_role = TYPEC_PWR_SOURCE;
+		port->data_role = TYPEC_HOST;
+		break;
+	case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
+		port->partner_type = TYPEC_PARTNER_DEBUG;
+		goto out;
+	case UCSI_CONSTAT_PARTNER_TYPE_AUDIO:
+		port->partner_type = TYPEC_PARTNER_AUDIO;
+		goto out;
+	}
+
+	switch (constat->pwr_op_mode) {
+	case UCSI_CONSTAT_PWR_OPMODE_NONE:
+	case UCSI_CONSTAT_PWR_OPMODE_DEFAULT:
+		port->pwr_opmode = TYPEC_PWR_MODE_USB;
+		break;
+	case UCSI_CONSTAT_PWR_OPMODE_BC:
+		port->partner_type = TYPEC_PARTNER_CHARGER;
+		port->pwr_opmode = TYPEC_PWR_MODE_BC1_2;
+		break;
+	case UCSI_CONSTAT_PWR_OPMODE_PD:
+		port->pwr_opmode = TYPEC_PWR_MODE_PD;
+		break;
+	case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_3:
+		port->pwr_opmode = TYPEC_PWR_MODE_1_5A;
+		break;
+	case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0:
+		port->pwr_opmode = TYPEC_PWR_MODE_3_0A;
+		break;
+	default:
+		break;
+	}
+out:
+	return typec_connect(port);
+}
+
+static void ucsi_disconnect(struct ucsi_connector *con)
+{
+	con->port->partner_type = TYPEC_PARTNER_NONE;
+	con->port->connected = false;
+	typec_disconnect(con->port);
+}
+
+static void ucsi_connector_change(struct work_struct *work)
+{
+	struct ucsi_connector *con = container_of(work, struct ucsi_connector,
+						  work);
+	struct ucsi_connector_status constat;
+
+	ucsi_ack(con->ucsi, UCSI_ACK_EVENT);
+
+	if (WARN_ON(ucsi_get_constat(con, &constat) != 0))
+		return;
+
+	if (constat.constat_change & UCSI_CONSTAT_CONNECT_CHANGE) {
+		if (constat.connected)
+			ucsi_connect(con, &constat);
+		else
+			ucsi_disconnect(con);
+	}
+}
+
+/**
+ * ucsi_interrupt - UCSI Notification Handler
+ * @ucsi: Source UCSI Interface for the notifications
+ *
+ * Handle notifications from @ucsi.
+ */
+int ucsi_interrupt(struct ucsi *ucsi)
+{
+	u32 cci = ucsi->ppm->data->cci;
+
+	if (!cci)
+		return 0;
+
+	if (UCSI_CCI_CONNECTOR_CHANGE(cci)) {
+		struct ucsi_connector *con = cci_to_connector(ucsi, cci);
+
+		schedule_work(&con->work);
+		return 1;
+	}
+
+	ucsi->status = 0;
+
+	/* REVISIT: We don't actually do anything with this for now */
+	if (cci & UCSI_CCI_BUSY)
+		ucsi->status = UCSI_BUSY;
+
+	if (cci & UCSI_CCI_ERROR)
+		ucsi->status = UCSI_ERROR;
+
+	if (cci & UCSI_CCI_ACK_CMD || cci & UCSI_CCI_CMD_COMPLETED)
+		complete(&ucsi->complete);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(ucsi_interrupt);
+
+/**
+ * ucsi_init - Initialize an UCSI Interface
+ * @ucsi: The UCSI Interface
+ *
+ * Registers all the USB Type-C ports governed by the PPM of @ucsi and enables
+ * all the notifications from the PPM.
+ */
+int ucsi_init(struct ucsi *ucsi)
+{
+	struct ucsi_control *ctrl = (void *)&ucsi->ppm->data->control;
+	struct ucsi_connector *con;
+	int ret;
+	int i;
+
+	/* Enable basic notifications */
+	ctrl->cmd = UCSI_SET_NOTIFICATION_ENABLE;
+	ctrl->data = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
+	ret = ucsi_run_cmd(ucsi, NULL, 0);
+	if (ret)
+		return ret;
+
+	/* Get PPM capabilities */
+	ctrl->cmd = UCSI_GET_CAPABILITY;
+	ret = ucsi_run_cmd(ucsi, &ucsi->cap, sizeof(ucsi->cap));
+	if (ret)
+		return ret;
+
+	ucsi->connector = kcalloc(ucsi->cap.num_connectors,
+				  sizeof(struct ucsi_connector), GFP_KERNEL);
+	if (!ucsi->connector)
+		return -ENOMEM;
+
+	for (i = 0, con = ucsi->connector; i < ucsi->cap.num_connectors;
+	     i++, con++) {
+		struct typec_capability *cap = &con->typec_cap;
+		struct ucsi_connector_status constat;
+
+		/* Get connector capability */
+		ctrl->cmd = UCSI_GET_CONNECTOR_CAPABILITY;
+		ctrl->data = i + 1;
+		ret = ucsi_run_cmd(ucsi, &con->cap, sizeof(con->cap));
+		if (ret)
+			goto err;
+
+		/* Register the connector */
+
+		if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
+			cap->type = TYPEC_PORT_DRP;
+		else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP)
+			cap->type = TYPEC_PORT_DFP;
+		else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP)
+			cap->type = TYPEC_PORT_UFP;
+
+		cap->usb_pd = !!(ucsi->cap.attributes &
+				       UCSI_CAP_ATTR_USB_PD);
+		cap->audio_accessory = !!(con->cap.op_mode &
+					  UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY);
+		cap->debug_accessory = !!(con->cap.op_mode &
+					  UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY);
+
+		/* TODO: Alt modes */
+
+		cap->dr_swap = ucsi_dr_swap;
+		cap->pr_swap = ucsi_pr_swap;
+
+		con->port = typec_register_port(ucsi->dev, cap);
+		if (IS_ERR(con->port)) {
+			ret = PTR_ERR(con->port);
+			goto err;
+		}
+
+		con->num = i + 1;
+		con->ucsi = ucsi;
+		INIT_WORK(&con->work, ucsi_connector_change);
+
+		/* Check if the connector is connected */
+		if (WARN_ON(ucsi_get_constat(con, &constat) != 0))
+			continue;
+
+		if (constat.connected)
+			ucsi_connect(con, &constat);
+	}
+
+	/* Enable all notifications */
+	ctrl->cmd = UCSI_SET_NOTIFICATION_ENABLE;
+	ctrl->data = UCSI_ENABLE_NTFY_ALL;
+	ret = ucsi_run_cmd(ucsi, NULL, 0);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	if (i > 0)
+		for (; i >= 0; i--, con--)
+			typec_unregister_port(con->port);
+
+	kfree(ucsi->connector);
+	return ret;
+}
+EXPORT_SYMBOL(ucsi_init);
+
+/**
+ * ucsi_register_ppm - Register UCSI PPM Interface
+ * @dev: Device interface to the PPM
+ * @ppm: The PPM interface
+ *
+ * Allocates an UCSI instance, associates it with @ppm and returns it to the
+ * caller.
+ */
+struct ucsi *ucsi_register_ppm(struct device *dev, struct ucsi_ppm *ppm)
+{
+	struct ucsi *ucsi;
+
+	ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL);
+	if (!ucsi)
+		return ERR_PTR(-ENOMEM);
+
+	init_completion(&ucsi->complete);
+	ucsi->dev = dev;
+	ucsi->ppm = ppm;
+
+	return ucsi;
+}
+EXPORT_SYMBOL_GPL(ucsi_register_ppm);
+
+/**
+ * ucsi_unregister_ppm - Unregister UCSI PPM Interface
+ * @ucsi: struct ucsi associated with the PPM
+ *
+ * Unregister an UCSI PPM that was created with ucsi_register().
+ */
+void ucsi_unregister_ppm(struct ucsi *ucsi)
+{
+	struct ucsi_connector *con;
+	int i;
+
+	/* Disable all notifications */
+	ucsi->ppm->data->control = UCSI_SET_NOTIFICATION_ENABLE;
+	ucsi->ppm->cmd(ucsi->ppm);
+
+	for (i = 0, con = ucsi->connector; i < ucsi->cap.num_connectors;
+	     i++, con++)
+		typec_unregister_port(con->port);
+
+	kfree(ucsi->connector);
+	kfree(ucsi);
+}
+EXPORT_SYMBOL_GPL(ucsi_unregister_ppm);
+
+MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("USB Type-C System Software Interface driver");
diff --git a/drivers/usb/type-c/ucsi.h b/drivers/usb/type-c/ucsi.h
new file mode 100644
index 0000000..0ec6366
--- /dev/null
+++ b/drivers/usb/type-c/ucsi.h
@@ -0,0 +1,219 @@
+
+#include <linux/types.h>
+
+/* -------------------------------------------------------------------------- */
+
+struct ucsi_data {
+	__u16 version;
+	__u16 RESERVED;
+	__u32 cci;
+	__u64 control;
+	__u32 message_in[4];
+	__u32 message_out[4];
+} __packed;
+
+struct ucsi_control {
+	__u8 cmd;
+	__u8 length;
+	__u64 data:48;
+} __packed;
+
+/* Command Status and Connector Change Indication (CCI) bits */
+#define UCSI_CCI_CONNECTOR_CHANGE(c)	((c >> 1) & 0x7f)
+#define UCSI_CCI_DATA_LENGTH(c)		((c >> 8) & 0xff)
+#define UCSI_CCI_NOT_SUPPORTED		BIT(25)
+#define UCSI_CCI_CANCEL_CMD		BIT(26)
+#define UCSI_CCI_RESET_CMD		BIT(27)
+#define UCSI_CCI_BUSY			BIT(28)
+#define UCSI_CCI_ACK_CMD		BIT(29)
+#define UCSI_CCI_ERROR			BIT(30)
+#define UCSI_CCI_CMD_COMPLETED		BIT(31)
+
+/* Commands */
+#define UCSI_PPM_RESET			0x01
+#define UCSI_CANCEL			0x02
+#define UCSI_CONNECTOR_RESET		0x03
+#define UCSI_ACK_CC_CI			0x04
+#define UCSI_SET_NOTIFICATION_ENABLE	0x05
+#define UCSI_GET_CAPABILITY		0x06
+#define UCSI_GET_CONNECTOR_CAPABILITY	0x07
+#define UCSI_SET_UOM			0x08
+#define UCSI_SET_UOR			0x09
+#define UCSI_SET_PDM			0x0A
+#define UCSI_SET_PDR			0x0B
+#define UCSI_GET_ALTERNATE_MODES	0x0C
+#define UCSI_GET_CAM_SUPPORTED		0x0D
+#define UCSI_GET_CURRENT_CAM		0x0E
+#define UCSI_SET_NEW_CAM		0x0F
+#define UCSI_GET_PDOS			0x10
+#define UCSI_GET_CABLE_PROPERTY		0x11
+#define UCSI_GET_CONNECTOR_STATUS	0x12
+#define UCSI_GET_ERROR_STATUS		0x13
+
+/* ACK_CC_CI commands */
+#define UCSI_ACK_EVENT			1
+#define UCSI_ACK_CMD			2
+
+/* Bits for SET_NOTIFICATION_ENABLE command */
+#define UCSI_ENABLE_NTFY_CMD_COMPLETE		BIT(0)
+#define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE	BIT(1)
+#define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE	BIT(2)
+#define UCSI_ENABLE_NTFY_CAP_CHANGE		BIT(5)
+#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE	BIT(6)
+#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE	BIT(7)
+#define UCSI_ENABLE_NTFY_CAM_CHANGE		BIT(8)
+#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE	BIT(9)
+#define UCSI_ENABLE_NTFY_PARTNER_CHANGE		BIT(11)
+#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE		BIT(12)
+#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE	BIT(14)
+#define UCSI_ENABLE_NTFY_ERROR			BIT(15)
+#define UCSI_ENABLE_NTFY_ALL			0xdbf3
+
+/* Error information returned by PPM in response to GET_ERROR_STATUS command. */
+#define UCSI_ERROR_UNREGONIZED_CMD		BIT(0)
+#define UCSI_ERROR_INVALID_CON_NUM		BIT(1)
+#define UCSI_ERROR_INVALID_CMD_ARGUMENT		BIT(2)
+#define UCSI_ERROR_INCOMPATIBLE_PARTNER		BIT(3)
+#define UCSI_ERROR_CC_COMMUNICATION_ERR		BIT(4)
+#define UCSI_ERROR_DEAD_BATTERY			BIT(5)
+#define UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL	BIT(6)
+
+/* Set USB Operation Role Command structure */
+struct ucsi_uor_cmd {
+	__u8 cmd;
+	__u8 length;
+	__u8 con_num:7;
+	__u64 role:3;
+#define UCSI_UOR_ROLE_DFP			BIT(0)
+#define UCSI_UOR_ROLE_UFP			BIT(1)
+#define UCSI_UOR_ROLE_DRP			BIT(2)
+	__u64 data:38;
+} __packed;
+
+/* Data structure filled by PPM in response to GET_CAPABILITY command. */
+struct ucsi_capability {
+	__u32 attributes;
+#define UCSI_CAP_ATTR_DISABLE_STATE		BIT(0)
+#define UCSI_CAP_ATTR_BATTERY_CHARGING		BIT(1)
+#define UCSI_CAP_ATTR_USB_PD			BIT(2)
+#define UCSI_CAP_ATTR_TYPEC_CURRENT		BIT(6)
+#define UCSI_CAP_ATTR_POWER_AC_SUPPLY		BIT(8)
+#define UCSI_CAP_ATTR_POWER_OTHER		BIT(10)
+#define UCSI_CAP_ATTR_POWER_VBUS		BIT(14)
+	__u8 num_connectors;
+	__u32 features:24;
+#define UCSI_CAP_SET_UOM			BIT(0)
+#define UCSI_CAP_SET_PDM			BIT(1)
+#define UCSI_CAP_ALT_MODE_DETAILS		BIT(2)
+#define UCSI_CAP_ALT_MODE_OVERRIDE		BIT(3)
+#define UCSI_CAP_PDO_DETAILS			BIT(4)
+#define UCSI_CAP_CABLE_DETAILS			BIT(5)
+#define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS	BIT(6)
+#define UCSI_CAP_PD_RESET			BIT(7)
+	__u8 num_alt_modes;
+	__u8 RESERVED;
+	__u16 bc_version;
+	__u16 pd_version;
+	__u16 typec_version;
+} __packed;
+
+/* Data structure filled by PPM in response to GET_CONNECTOR_CAPABILITY cmd. */
+struct ucsi_connector_capability {
+	__u8 op_mode;
+#define UCSI_CONCAP_OPMODE_DFP			BIT(0)
+#define UCSI_CONCAP_OPMODE_UFP			BIT(1)
+#define UCSI_CONCAP_OPMODE_DRP			BIT(2)
+#define UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY	BIT(3)
+#define UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY	BIT(4)
+#define UCSI_CONCAP_OPMODE_USB2			BIT(5)
+#define UCSI_CONCAP_OPMODE_USB3			BIT(6)
+#define UCSI_CONCAP_OPMODE_ALT_MODE		BIT(7)
+	__u8 provider:1;
+	__u8 consumer:1;
+} __packed;
+
+/* Data structure filled by PPM in response to GET_ALTERNATE_MODES command. */
+struct ucsi_alt_modes {
+	__u32 svid0;
+	__u16 mid0;
+	__u32 svid1;
+	__u16 mid1;
+} __packed;
+
+/* Data structure filled by PPM in response to GET_CABLE_PROPERTY command. */
+struct ucsi_cable_property {
+	__u16 speed_supported;
+	__u8 current_capability;
+	__u8 vbus_in_cable:1;
+	__u8 active_cable:1;
+	__u8 directionality:1;
+	__u8 plug_type:2;
+#define UCSI_CABLE_PROPERTY_PLUG_TYPE_A		0
+#define UCSI_CABLE_PROPERTY_PLUG_TYPE_B		1
+#define UCSI_CABLE_PROPERTY_PLUG_TYPE_C		2
+#define UCSI_CABLE_PROPERTY_PLUG_OTHER		3
+	__u8 mode_support:1;
+	__u8 RESERVED_2:2;
+	__u8 latency:4;
+	__u8 RESERVED_4:4;
+} __packed;
+
+/* Data structure filled by PPM in response to GET_CONNECTOR_STATUS command. */
+struct ucsi_connector_status {
+	__u16 constat_change;
+#define UCSI_CONSTAT_EXT_SUPPLY_CHANGE		BIT(1)
+#define UCSI_CONSTAT_POWER_OPMODE_CHANGE	BIT(2)
+#define UCSI_CONSTAT_PDOS_CHANGE		BIT(5)
+#define UCSI_CONSTAT_POWER_LEVEL_CHANGE		BIT(6)
+#define UCSI_CONSTAT_PD_RESET_COMPLETE		BIT(7)
+#define UCSI_CONSTAT_CAM_CHANGE			BIT(8)
+#define UCSI_CONSTAT_BC_CHANGE			BIT(9)
+#define UCSI_CONSTAT_PARTNER_CHANGE		BIT(11)
+#define UCSI_CONSTAT_POWER_DIR_CHANGE		BIT(12)
+#define UCSI_CONSTAT_CONNECT_CHANGE		BIT(14)
+#define UCSI_CONSTAT_ERROR			BIT(15)
+	__u16 pwr_op_mode:3;
+#define UCSI_CONSTAT_PWR_OPMODE_NONE		0
+#define UCSI_CONSTAT_PWR_OPMODE_DEFAULT		1
+#define UCSI_CONSTAT_PWR_OPMODE_BC		2
+#define UCSI_CONSTAT_PWR_OPMODE_PD		3
+#define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_3	4
+#define UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0	5
+	__u16 connected:1;
+	__u16 pwr_dir:1;
+	__u16 partner_flags:8;
+#define UCSI_CONSTAT_PARTNER_FLAG_USB		BIT(0)
+#define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE	BIT(1)
+	__u16 partner_type:3;
+#define UCSI_CONSTAT_PARTNER_TYPE_DFP		1
+#define UCSI_CONSTAT_PARTNER_TYPE_UFP		2
+#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_NO_UFP	3 /* Powered Cable */
+#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP	4 /* Powered Cable */
+#define UCSI_CONSTAT_PARTNER_TYPE_DEBUG		5
+#define UCSI_CONSTAT_PARTNER_TYPE_AUDIO		6
+	__u32 request_data_obj;
+	__u8 bc_status;
+#define UCSI_CONSTAT_BC_NOT_CHARGING		0
+#define UCSI_CONSTAT_BC_NOMINAL_CHARGING	1
+#define UCSI_CONSTAT_BC_SLOW_CHARGING		2
+#define UCSI_CONSTAT_BC_TRICLE_CHARGING		3
+} __packed;
+
+/* -------------------------------------------------------------------------- */
+
+struct ucsi;
+
+/*
+ * struct ucsi_ppm - Interface to an UCSI Platform Policy Manager
+ * @data: memory location to the UCSI data structures
+ * @cmd: UCSI command execution routine
+ */
+struct ucsi_ppm {
+	struct ucsi_data *data;
+	int (*cmd)(struct ucsi_ppm *);
+};
+
+struct ucsi *ucsi_register_ppm(struct device *, struct ucsi_ppm *);
+void ucsi_unregister_ppm(struct ucsi *);
+int ucsi_init(struct ucsi *);
+int ucsi_interrupt(struct ucsi *);
-- 
2.7.0

  parent reply	other threads:[~2016-02-09 17:03 UTC|newest]

Thread overview: 90+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-09 17:01 [PATCH 0/3] usb: USB Type-C Class and driver for UCSI Heikki Krogerus
2016-02-09 17:01 ` [PATCH 1/3] usb: USB Type-C Connector Class Heikki Krogerus
2016-02-09 18:20   ` Greg KH
2016-02-10 10:38     ` Heikki Krogerus
2016-02-10 17:26       ` Greg KH
2016-02-11 14:07         ` Heikki Krogerus
2016-02-10 10:49   ` Oliver Neukum
2016-02-10 11:05     ` Andy Shevchenko
2016-02-10 11:11       ` Heikki Krogerus
2016-02-10 11:14         ` Andy Shevchenko
2016-02-10 11:23     ` Heikki Krogerus
2016-02-15 15:16       ` Oliver Neukum
2016-02-11  8:55     ` Felipe Balbi
2016-02-11  9:08       ` Oliver Neukum
2016-02-11 14:51         ` Heikki Krogerus
2016-02-11 14:36       ` Heikki Krogerus
2016-02-11 14:56         ` Oliver Neukum
2016-02-17 14:07   ` Oliver Neukum
2016-02-18  8:47     ` Heikki Krogerus
2016-02-18  9:21       ` Oliver Neukum
2016-02-18 13:09         ` Heikki Krogerus
2016-02-18  9:35       ` Oliver Neukum
2016-02-18 13:25         ` Heikki Krogerus
2016-02-18 13:44           ` Oliver Neukum
2016-02-18 15:13             ` Heikki Krogerus
2016-02-26 13:09             ` Heikki Krogerus
2016-02-09 17:01 ` Heikki Krogerus [this message]
2016-02-09 18:21   ` [PATCH 2/3] usb: type-c: USB Type-C Connector System Software Interface Greg KH
2016-02-10 10:30     ` Heikki Krogerus
2016-02-10 17:20       ` Greg KH
2016-02-11 13:50         ` Heikki Krogerus
2016-02-15 15:30           ` Oliver Neukum
2016-02-16  9:22             ` Heikki Krogerus
2016-02-16 13:39               ` Oliver Neukum
2016-02-17  7:58                 ` Heikki Krogerus
2016-02-17  9:03                   ` Oliver Neukum
2016-02-17 10:29                     ` Felipe Balbi
2016-02-17 10:36                       ` Oliver Neukum
2016-02-17 11:11                         ` Heikki Krogerus
2016-02-17 13:36                           ` Felipe Balbi
2016-02-17 14:28                             ` Heikki Krogerus
2016-02-18  9:07                               ` Peter Chen
2016-02-18 10:44                                 ` Heikki Krogerus
2016-02-18 10:37                               ` Rajaram R
2016-02-18 10:47                                 ` Heikki Krogerus
2016-02-18 11:06                                   ` Rajaram R
2016-02-17 13:34                         ` Felipe Balbi
2016-02-17 13:51                           ` Oliver Neukum
2016-02-18  7:08                             ` Felipe Balbi
2016-02-18 10:18                               ` Oliver Neukum
2016-02-18 10:30                                 ` Felipe Balbi
2016-02-18 10:40                                   ` Oliver Neukum
2016-02-18  9:29       ` Peter Chen
2016-02-18  9:44         ` Oliver Neukum
2016-02-10 11:19   ` Oliver Neukum
2016-02-10 12:04     ` Heikki Krogerus
2016-02-10 11:56   ` Andy Shevchenko
2016-02-10 13:21     ` Oliver Neukum
2016-02-10 14:02       ` Andy Shevchenko
2016-02-10 15:11         ` Bjørn Mork
2016-02-11  8:26           ` Andy Shevchenko
2016-02-11  8:59             ` Bjørn Mork
2016-02-10 14:15     ` Oliver Neukum
2016-02-10 14:24       ` Andy Shevchenko
2016-02-10 15:08         ` Oliver Neukum
     [not found]           ` <CAHp75VfmGsskf7Cmni3b4=tCbkPsR8d3jPYiv93Lm6DM9gq1-g@mail.gmail.com>
2016-02-11  8:13             ` Fwd: " Andy Shevchenko
2016-02-11 14:10               ` Heikki Krogerus
2016-02-10 13:04   ` Oliver Neukum
2016-02-11 14:08     ` Heikki Krogerus
2016-02-09 17:01 ` [PATCH 3/3] usb: type-c: UCSI ACPI driver Heikki Krogerus
2016-02-09 18:22   ` Greg KH
2016-02-10 10:23     ` Heikki Krogerus
2016-02-17 18:53 ` [PATCH 0/3] usb: USB Type-C Class and driver for UCSI Oliver Neukum
2016-02-18  9:21   ` Heikki Krogerus
2016-02-17 19:34 ` Rajaram R
2016-02-18 11:05   ` Heikki Krogerus
2016-02-18 11:15     ` Oliver Neukum
2016-05-05  3:05 ` Guenter Roeck
2016-05-06  6:50   ` Felipe Balbi
2016-05-06  8:05     ` Guenter Roeck
2016-05-06  8:29       ` Heikki Krogerus
2016-05-06 14:10         ` Guenter Roeck
2016-05-06  8:23     ` Heikki Krogerus
2016-05-06  8:08   ` Heikki Krogerus
2016-05-06 14:08     ` Guenter Roeck
2016-05-11  3:14     ` Guenter Roeck
2016-05-11  9:40       ` Heikki Krogerus
2016-05-11 14:47         ` Guenter Roeck
2016-05-13 14:23           ` Heikki Krogerus
2016-05-13 17:48             ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1455037283-106479-3-git-send-email-heikki.krogerus@linux.intel.com \
    --to=heikki.krogerus@linux.intel.com \
    --cc=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.