-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
usb: typec: Add support for UCSI interface
UCSI - USB Type-C Connector System Software Interface - is a specification that defines set of registers and data structures for controlling the USB Type-C ports. It's designed for systems where an embedded controller (EC) is in charge of the USB Type-C PHY or USB Power Delivery controller. It is designed for systems with EC, but it is not limited to them, and for example some USB Power Delivery controllers will use it as their direct control interface. With UCSI the EC (or USB PD controller) acts as the port manager, implementing all USB Type-C and Power Delivery state machines. The OS can use the interfaces for reading the status of the ports and controlling basic operations like role swapping. The UCSI specification highlights the fact that it does not define the interface method (PCI/I2C/ACPI/etc.). Therefore the driver is implemented as library and every supported interface method needs its own driver. Driver for ACPI is provided in separate patch following this one. The initial driver includes support for all required features from UCSI specification version 1.0 (getting connector capabilities and status, and support for power and data role swapping), but none of the optional UCSI features (alternate modes, power source capabilities, and cable capabilities). Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- Loading branch information
Heikki Krogerus
authored and
Greg Kroah-Hartman
committed
Jun 27, 2017
1 parent
c68bb0e
commit c1b0bc2
Showing
9 changed files
with
1,367 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
obj-$(CONFIG_TYPEC) += typec.o | ||
obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o | ||
obj-$(CONFIG_TYPEC_UCSI) += ucsi/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
config TYPEC_UCSI | ||
tristate "USB Type-C Connector System Software Interface driver" | ||
depends on !CPU_BIG_ENDIAN | ||
select TYPEC | ||
help | ||
USB Type-C Connector System Software Interface (UCSI) is a | ||
specification for an interface that allows the operating system to | ||
control the USB Type-C ports. On UCSI system the USB Type-C ports | ||
function autonomously by default, but in order to get the status of | ||
the ports and support basic operations like role swapping, the driver | ||
is required. UCSI is available on most of the new Intel based systems | ||
that are equipped with Embedded Controller and USB Type-C ports. | ||
|
||
UCSI specification does not define the interface method, so depending | ||
on the platform, ACPI, PCI, I2C, etc. may be used. Therefore this | ||
driver only provides the core part, and separate drivers are needed | ||
for every supported interface method. | ||
|
||
The UCSI specification can be downloaded from: | ||
http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html | ||
|
||
To compile the driver as a module, choose M here: the module will be | ||
called typec_ucsi. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
CFLAGS_trace.o := -I$(src) | ||
|
||
obj-$(CONFIG_TYPEC_UCSI) += typec_ucsi.o | ||
|
||
typec_ucsi-y := ucsi.o | ||
|
||
typec_ucsi-$(CONFIG_FTRACE) += trace.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#ifndef __UCSI_DEBUG_H | ||
#define __UCSI_DEBUG_H | ||
|
||
#include "ucsi.h" | ||
|
||
static const char * const ucsi_cmd_strs[] = { | ||
[0] = "Unknown command", | ||
[UCSI_PPM_RESET] = "PPM_RESET", | ||
[UCSI_CANCEL] = "CANCEL", | ||
[UCSI_CONNECTOR_RESET] = "CONNECTOR_RESET", | ||
[UCSI_ACK_CC_CI] = "ACK_CC_CI", | ||
[UCSI_SET_NOTIFICATION_ENABLE] = "SET_NOTIFICATION_ENABLE", | ||
[UCSI_GET_CAPABILITY] = "GET_CAPABILITY", | ||
[UCSI_GET_CONNECTOR_CAPABILITY] = "GET_CONNECTOR_CAPABILITY", | ||
[UCSI_SET_UOM] = "SET_UOM", | ||
[UCSI_SET_UOR] = "SET_UOR", | ||
[UCSI_SET_PDM] = "SET_PDM", | ||
[UCSI_SET_PDR] = "SET_PDR", | ||
[UCSI_GET_ALTERNATE_MODES] = "GET_ALTERNATE_MODES", | ||
[UCSI_GET_CAM_SUPPORTED] = "GET_CAM_SUPPORTED", | ||
[UCSI_GET_CURRENT_CAM] = "GET_CURRENT_CAM", | ||
[UCSI_SET_NEW_CAM] = "SET_NEW_CAM", | ||
[UCSI_GET_PDOS] = "GET_PDOS", | ||
[UCSI_GET_CABLE_PROPERTY] = "GET_CABLE_PROPERTY", | ||
[UCSI_GET_CONNECTOR_STATUS] = "GET_CONNECTOR_STATUS", | ||
[UCSI_GET_ERROR_STATUS] = "GET_ERROR_STATUS", | ||
}; | ||
|
||
static inline const char *ucsi_cmd_str(u64 raw_cmd) | ||
{ | ||
u8 cmd = raw_cmd & GENMASK(7, 0); | ||
|
||
return ucsi_cmd_strs[(cmd >= ARRAY_SIZE(ucsi_cmd_strs)) ? 0 : cmd]; | ||
} | ||
|
||
static const char * const ucsi_ack_strs[] = { | ||
[0] = "", | ||
[UCSI_ACK_EVENT] = "event", | ||
[UCSI_ACK_CMD] = "command", | ||
}; | ||
|
||
static inline const char *ucsi_ack_str(u8 ack) | ||
{ | ||
return ucsi_ack_strs[(ack >= ARRAY_SIZE(ucsi_ack_strs)) ? 0 : ack]; | ||
} | ||
|
||
static inline const char *ucsi_cci_str(u32 cci) | ||
{ | ||
if (cci & GENMASK(7, 0)) { | ||
if (cci & BIT(29)) | ||
return "Event pending (ACK completed)"; | ||
if (cci & BIT(31)) | ||
return "Event pending (command completed)"; | ||
return "Connector Change"; | ||
} | ||
if (cci & BIT(29)) | ||
return "ACK completed"; | ||
if (cci & BIT(31)) | ||
return "Command completed"; | ||
|
||
return ""; | ||
} | ||
|
||
#endif /* __UCSI_DEBUG_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#define CREATE_TRACE_POINTS | ||
#include "trace.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
|
||
#undef TRACE_SYSTEM | ||
#define TRACE_SYSTEM ucsi | ||
|
||
#if !defined(__UCSI_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
#define __UCSI_TRACE_H | ||
|
||
#include <linux/tracepoint.h> | ||
#include "ucsi.h" | ||
#include "debug.h" | ||
|
||
DECLARE_EVENT_CLASS(ucsi_log_ack, | ||
TP_PROTO(u8 ack), | ||
TP_ARGS(ack), | ||
TP_STRUCT__entry( | ||
__field(u8, ack) | ||
), | ||
TP_fast_assign( | ||
__entry->ack = ack; | ||
), | ||
TP_printk("ACK %s", ucsi_ack_str(__entry->ack)) | ||
); | ||
|
||
DEFINE_EVENT(ucsi_log_ack, ucsi_ack, | ||
TP_PROTO(u8 ack), | ||
TP_ARGS(ack) | ||
); | ||
|
||
DECLARE_EVENT_CLASS(ucsi_log_control, | ||
TP_PROTO(struct ucsi_control *ctrl), | ||
TP_ARGS(ctrl), | ||
TP_STRUCT__entry( | ||
__field(u64, ctrl) | ||
), | ||
TP_fast_assign( | ||
__entry->ctrl = ctrl->raw_cmd; | ||
), | ||
TP_printk("control=%08llx (%s)", __entry->ctrl, | ||
ucsi_cmd_str(__entry->ctrl)) | ||
); | ||
|
||
DEFINE_EVENT(ucsi_log_control, ucsi_command, | ||
TP_PROTO(struct ucsi_control *ctrl), | ||
TP_ARGS(ctrl) | ||
); | ||
|
||
DECLARE_EVENT_CLASS(ucsi_log_command, | ||
TP_PROTO(struct ucsi_control *ctrl, int ret), | ||
TP_ARGS(ctrl, ret), | ||
TP_STRUCT__entry( | ||
__field(u64, ctrl) | ||
__field(int, ret) | ||
), | ||
TP_fast_assign( | ||
__entry->ctrl = ctrl->raw_cmd; | ||
__entry->ret = ret; | ||
), | ||
TP_printk("%s -> %s (err=%d)", ucsi_cmd_str(__entry->ctrl), | ||
__entry->ret < 0 ? "FAIL" : "OK", | ||
__entry->ret < 0 ? __entry->ret : 0) | ||
); | ||
|
||
DEFINE_EVENT(ucsi_log_command, ucsi_run_command, | ||
TP_PROTO(struct ucsi_control *ctrl, int ret), | ||
TP_ARGS(ctrl, ret) | ||
); | ||
|
||
DEFINE_EVENT(ucsi_log_command, ucsi_reset_ppm, | ||
TP_PROTO(struct ucsi_control *ctrl, int ret), | ||
TP_ARGS(ctrl, ret) | ||
); | ||
|
||
DECLARE_EVENT_CLASS(ucsi_log_cci, | ||
TP_PROTO(u32 cci), | ||
TP_ARGS(cci), | ||
TP_STRUCT__entry( | ||
__field(u32, cci) | ||
), | ||
TP_fast_assign( | ||
__entry->cci = cci; | ||
), | ||
TP_printk("CCI=%08x %s", __entry->cci, ucsi_cci_str(__entry->cci)) | ||
); | ||
|
||
DEFINE_EVENT(ucsi_log_cci, ucsi_notify, | ||
TP_PROTO(u32 cci), | ||
TP_ARGS(cci) | ||
); | ||
|
||
DECLARE_EVENT_CLASS(ucsi_log_connector_status, | ||
TP_PROTO(int port, struct ucsi_connector_status *status), | ||
TP_ARGS(port, status), | ||
TP_STRUCT__entry( | ||
__field(int, port) | ||
__field(u16, change) | ||
__field(u8, opmode) | ||
__field(u8, connected) | ||
__field(u8, pwr_dir) | ||
__field(u8, partner_flags) | ||
__field(u8, partner_type) | ||
__field(u32, request_data_obj) | ||
__field(u8, bc_status) | ||
), | ||
TP_fast_assign( | ||
__entry->port = port - 1; | ||
__entry->change = status->change; | ||
__entry->opmode = status->pwr_op_mode; | ||
__entry->connected = status->connected; | ||
__entry->pwr_dir = status->pwr_dir; | ||
__entry->partner_flags = status->partner_flags; | ||
__entry->partner_type = status->partner_type; | ||
__entry->request_data_obj = status->request_data_obj; | ||
__entry->bc_status = status->bc_status; | ||
), | ||
TP_printk("port%d status: change=%04x, opmode=%x, connected=%d, " | ||
"sourcing=%d, partner_flags=%x, partner_type=%x, " | ||
"request_data_obj=%08x, BC status=%x", __entry->port, | ||
__entry->change, __entry->opmode, __entry->connected, | ||
__entry->pwr_dir, __entry->partner_flags, __entry->partner_type, | ||
__entry->request_data_obj, __entry->bc_status) | ||
); | ||
|
||
DEFINE_EVENT(ucsi_log_connector_status, ucsi_connector_change, | ||
TP_PROTO(int port, struct ucsi_connector_status *status), | ||
TP_ARGS(port, status) | ||
); | ||
|
||
DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port, | ||
TP_PROTO(int port, struct ucsi_connector_status *status), | ||
TP_ARGS(port, status) | ||
); | ||
|
||
#endif /* __UCSI_TRACE_H */ | ||
|
||
/* This part must be outside protection */ | ||
|
||
#undef TRACE_INCLUDE_PATH | ||
#define TRACE_INCLUDE_PATH . | ||
|
||
#undef TRACE_INCLUDE_FILE | ||
#define TRACE_INCLUDE_FILE trace | ||
|
||
#include <trace/define_trace.h> |
Oops, something went wrong.