Skip to content

Commit c1b0bc2

Browse files
Heikki Krogerusgregkh
authored andcommitted
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 <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent c68bb0e commit c1b0bc2

File tree

9 files changed

+1367
-0
lines changed

9 files changed

+1367
-0
lines changed

drivers/usb/typec/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ config TYPEC_WCOVE
1919
To compile this driver as module, choose M here: the module will be
2020
called typec_wcove
2121

22+
source "drivers/usb/typec/ucsi/Kconfig"
23+
2224
endmenu

drivers/usb/typec/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
obj-$(CONFIG_TYPEC) += typec.o
22
obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o
3+
obj-$(CONFIG_TYPEC_UCSI) += ucsi/

drivers/usb/typec/ucsi/Kconfig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
config TYPEC_UCSI
2+
tristate "USB Type-C Connector System Software Interface driver"
3+
depends on !CPU_BIG_ENDIAN
4+
select TYPEC
5+
help
6+
USB Type-C Connector System Software Interface (UCSI) is a
7+
specification for an interface that allows the operating system to
8+
control the USB Type-C ports. On UCSI system the USB Type-C ports
9+
function autonomously by default, but in order to get the status of
10+
the ports and support basic operations like role swapping, the driver
11+
is required. UCSI is available on most of the new Intel based systems
12+
that are equipped with Embedded Controller and USB Type-C ports.
13+
14+
UCSI specification does not define the interface method, so depending
15+
on the platform, ACPI, PCI, I2C, etc. may be used. Therefore this
16+
driver only provides the core part, and separate drivers are needed
17+
for every supported interface method.
18+
19+
The UCSI specification can be downloaded from:
20+
http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html
21+
22+
To compile the driver as a module, choose M here: the module will be
23+
called typec_ucsi.

drivers/usb/typec/ucsi/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CFLAGS_trace.o := -I$(src)
2+
3+
obj-$(CONFIG_TYPEC_UCSI) += typec_ucsi.o
4+
5+
typec_ucsi-y := ucsi.o
6+
7+
typec_ucsi-$(CONFIG_FTRACE) += trace.o

drivers/usb/typec/ucsi/debug.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#ifndef __UCSI_DEBUG_H
2+
#define __UCSI_DEBUG_H
3+
4+
#include "ucsi.h"
5+
6+
static const char * const ucsi_cmd_strs[] = {
7+
[0] = "Unknown command",
8+
[UCSI_PPM_RESET] = "PPM_RESET",
9+
[UCSI_CANCEL] = "CANCEL",
10+
[UCSI_CONNECTOR_RESET] = "CONNECTOR_RESET",
11+
[UCSI_ACK_CC_CI] = "ACK_CC_CI",
12+
[UCSI_SET_NOTIFICATION_ENABLE] = "SET_NOTIFICATION_ENABLE",
13+
[UCSI_GET_CAPABILITY] = "GET_CAPABILITY",
14+
[UCSI_GET_CONNECTOR_CAPABILITY] = "GET_CONNECTOR_CAPABILITY",
15+
[UCSI_SET_UOM] = "SET_UOM",
16+
[UCSI_SET_UOR] = "SET_UOR",
17+
[UCSI_SET_PDM] = "SET_PDM",
18+
[UCSI_SET_PDR] = "SET_PDR",
19+
[UCSI_GET_ALTERNATE_MODES] = "GET_ALTERNATE_MODES",
20+
[UCSI_GET_CAM_SUPPORTED] = "GET_CAM_SUPPORTED",
21+
[UCSI_GET_CURRENT_CAM] = "GET_CURRENT_CAM",
22+
[UCSI_SET_NEW_CAM] = "SET_NEW_CAM",
23+
[UCSI_GET_PDOS] = "GET_PDOS",
24+
[UCSI_GET_CABLE_PROPERTY] = "GET_CABLE_PROPERTY",
25+
[UCSI_GET_CONNECTOR_STATUS] = "GET_CONNECTOR_STATUS",
26+
[UCSI_GET_ERROR_STATUS] = "GET_ERROR_STATUS",
27+
};
28+
29+
static inline const char *ucsi_cmd_str(u64 raw_cmd)
30+
{
31+
u8 cmd = raw_cmd & GENMASK(7, 0);
32+
33+
return ucsi_cmd_strs[(cmd >= ARRAY_SIZE(ucsi_cmd_strs)) ? 0 : cmd];
34+
}
35+
36+
static const char * const ucsi_ack_strs[] = {
37+
[0] = "",
38+
[UCSI_ACK_EVENT] = "event",
39+
[UCSI_ACK_CMD] = "command",
40+
};
41+
42+
static inline const char *ucsi_ack_str(u8 ack)
43+
{
44+
return ucsi_ack_strs[(ack >= ARRAY_SIZE(ucsi_ack_strs)) ? 0 : ack];
45+
}
46+
47+
static inline const char *ucsi_cci_str(u32 cci)
48+
{
49+
if (cci & GENMASK(7, 0)) {
50+
if (cci & BIT(29))
51+
return "Event pending (ACK completed)";
52+
if (cci & BIT(31))
53+
return "Event pending (command completed)";
54+
return "Connector Change";
55+
}
56+
if (cci & BIT(29))
57+
return "ACK completed";
58+
if (cci & BIT(31))
59+
return "Command completed";
60+
61+
return "";
62+
}
63+
64+
#endif /* __UCSI_DEBUG_H */

drivers/usb/typec/ucsi/trace.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define CREATE_TRACE_POINTS
2+
#include "trace.h"

drivers/usb/typec/ucsi/trace.h

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
2+
#undef TRACE_SYSTEM
3+
#define TRACE_SYSTEM ucsi
4+
5+
#if !defined(__UCSI_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
6+
#define __UCSI_TRACE_H
7+
8+
#include <linux/tracepoint.h>
9+
#include "ucsi.h"
10+
#include "debug.h"
11+
12+
DECLARE_EVENT_CLASS(ucsi_log_ack,
13+
TP_PROTO(u8 ack),
14+
TP_ARGS(ack),
15+
TP_STRUCT__entry(
16+
__field(u8, ack)
17+
),
18+
TP_fast_assign(
19+
__entry->ack = ack;
20+
),
21+
TP_printk("ACK %s", ucsi_ack_str(__entry->ack))
22+
);
23+
24+
DEFINE_EVENT(ucsi_log_ack, ucsi_ack,
25+
TP_PROTO(u8 ack),
26+
TP_ARGS(ack)
27+
);
28+
29+
DECLARE_EVENT_CLASS(ucsi_log_control,
30+
TP_PROTO(struct ucsi_control *ctrl),
31+
TP_ARGS(ctrl),
32+
TP_STRUCT__entry(
33+
__field(u64, ctrl)
34+
),
35+
TP_fast_assign(
36+
__entry->ctrl = ctrl->raw_cmd;
37+
),
38+
TP_printk("control=%08llx (%s)", __entry->ctrl,
39+
ucsi_cmd_str(__entry->ctrl))
40+
);
41+
42+
DEFINE_EVENT(ucsi_log_control, ucsi_command,
43+
TP_PROTO(struct ucsi_control *ctrl),
44+
TP_ARGS(ctrl)
45+
);
46+
47+
DECLARE_EVENT_CLASS(ucsi_log_command,
48+
TP_PROTO(struct ucsi_control *ctrl, int ret),
49+
TP_ARGS(ctrl, ret),
50+
TP_STRUCT__entry(
51+
__field(u64, ctrl)
52+
__field(int, ret)
53+
),
54+
TP_fast_assign(
55+
__entry->ctrl = ctrl->raw_cmd;
56+
__entry->ret = ret;
57+
),
58+
TP_printk("%s -> %s (err=%d)", ucsi_cmd_str(__entry->ctrl),
59+
__entry->ret < 0 ? "FAIL" : "OK",
60+
__entry->ret < 0 ? __entry->ret : 0)
61+
);
62+
63+
DEFINE_EVENT(ucsi_log_command, ucsi_run_command,
64+
TP_PROTO(struct ucsi_control *ctrl, int ret),
65+
TP_ARGS(ctrl, ret)
66+
);
67+
68+
DEFINE_EVENT(ucsi_log_command, ucsi_reset_ppm,
69+
TP_PROTO(struct ucsi_control *ctrl, int ret),
70+
TP_ARGS(ctrl, ret)
71+
);
72+
73+
DECLARE_EVENT_CLASS(ucsi_log_cci,
74+
TP_PROTO(u32 cci),
75+
TP_ARGS(cci),
76+
TP_STRUCT__entry(
77+
__field(u32, cci)
78+
),
79+
TP_fast_assign(
80+
__entry->cci = cci;
81+
),
82+
TP_printk("CCI=%08x %s", __entry->cci, ucsi_cci_str(__entry->cci))
83+
);
84+
85+
DEFINE_EVENT(ucsi_log_cci, ucsi_notify,
86+
TP_PROTO(u32 cci),
87+
TP_ARGS(cci)
88+
);
89+
90+
DECLARE_EVENT_CLASS(ucsi_log_connector_status,
91+
TP_PROTO(int port, struct ucsi_connector_status *status),
92+
TP_ARGS(port, status),
93+
TP_STRUCT__entry(
94+
__field(int, port)
95+
__field(u16, change)
96+
__field(u8, opmode)
97+
__field(u8, connected)
98+
__field(u8, pwr_dir)
99+
__field(u8, partner_flags)
100+
__field(u8, partner_type)
101+
__field(u32, request_data_obj)
102+
__field(u8, bc_status)
103+
),
104+
TP_fast_assign(
105+
__entry->port = port - 1;
106+
__entry->change = status->change;
107+
__entry->opmode = status->pwr_op_mode;
108+
__entry->connected = status->connected;
109+
__entry->pwr_dir = status->pwr_dir;
110+
__entry->partner_flags = status->partner_flags;
111+
__entry->partner_type = status->partner_type;
112+
__entry->request_data_obj = status->request_data_obj;
113+
__entry->bc_status = status->bc_status;
114+
),
115+
TP_printk("port%d status: change=%04x, opmode=%x, connected=%d, "
116+
"sourcing=%d, partner_flags=%x, partner_type=%x, "
117+
"request_data_obj=%08x, BC status=%x", __entry->port,
118+
__entry->change, __entry->opmode, __entry->connected,
119+
__entry->pwr_dir, __entry->partner_flags, __entry->partner_type,
120+
__entry->request_data_obj, __entry->bc_status)
121+
);
122+
123+
DEFINE_EVENT(ucsi_log_connector_status, ucsi_connector_change,
124+
TP_PROTO(int port, struct ucsi_connector_status *status),
125+
TP_ARGS(port, status)
126+
);
127+
128+
DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port,
129+
TP_PROTO(int port, struct ucsi_connector_status *status),
130+
TP_ARGS(port, status)
131+
);
132+
133+
#endif /* __UCSI_TRACE_H */
134+
135+
/* This part must be outside protection */
136+
137+
#undef TRACE_INCLUDE_PATH
138+
#define TRACE_INCLUDE_PATH .
139+
140+
#undef TRACE_INCLUDE_FILE
141+
#define TRACE_INCLUDE_FILE trace
142+
143+
#include <trace/define_trace.h>

0 commit comments

Comments
 (0)