aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/usb
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/usb')
-rw-r--r--include/linux/usb/hcd.h8
-rw-r--r--include/linux/usb/pd.h185
-rw-r--r--include/linux/usb/pd_ado.h42
-rw-r--r--include/linux/usb/pd_ext_sdb.h31
-rw-r--r--include/linux/usb/quirks.h3
-rw-r--r--include/linux/usb/role.h53
-rw-r--r--include/linux/usb/tcpm.h15
-rw-r--r--include/linux/usb/typec.h28
-rw-r--r--include/linux/usb/typec_mux.h55
9 files changed, 391 insertions, 29 deletions
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 176900528822..aef50cb2ed1b 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -103,7 +103,7 @@ struct usb_hcd {
103 * other external phys should be software-transparent 103 * other external phys should be software-transparent
104 */ 104 */
105 struct usb_phy *usb_phy; 105 struct usb_phy *usb_phy;
106 struct phy *phy; 106 struct usb_phy_roothub *phy_roothub;
107 107
108 /* Flags that need to be manipulated atomically because they can 108 /* Flags that need to be manipulated atomically because they can
109 * change while the host controller is running. Always use 109 * change while the host controller is running. Always use
@@ -151,6 +151,12 @@ struct usb_hcd {
151 unsigned msix_enabled:1; /* driver has MSI-X enabled? */ 151 unsigned msix_enabled:1; /* driver has MSI-X enabled? */
152 unsigned msi_enabled:1; /* driver has MSI enabled? */ 152 unsigned msi_enabled:1; /* driver has MSI enabled? */
153 unsigned remove_phy:1; /* auto-remove USB phy */ 153 unsigned remove_phy:1; /* auto-remove USB phy */
154 /*
155 * do not manage the PHY state in the HCD core, instead let the driver
156 * handle this (for example if the PHY can only be turned on after a
157 * specific event)
158 */
159 unsigned skip_phy_initialization:1;
154 160
155 /* The next flag is a stopgap, to be removed when all the HCDs 161 /* The next flag is a stopgap, to be removed when all the HCDs
156 * support the new root-hub polling mechanism. */ 162 * support the new root-hub polling mechanism. */
diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h
index b3d41d7409b3..ff359bdfdc7b 100644
--- a/include/linux/usb/pd.h
+++ b/include/linux/usb/pd.h
@@ -35,6 +35,13 @@ enum pd_ctrl_msg_type {
35 PD_CTRL_WAIT = 12, 35 PD_CTRL_WAIT = 12,
36 PD_CTRL_SOFT_RESET = 13, 36 PD_CTRL_SOFT_RESET = 13,
37 /* 14-15 Reserved */ 37 /* 14-15 Reserved */
38 PD_CTRL_NOT_SUPP = 16,
39 PD_CTRL_GET_SOURCE_CAP_EXT = 17,
40 PD_CTRL_GET_STATUS = 18,
41 PD_CTRL_FR_SWAP = 19,
42 PD_CTRL_GET_PPS_STATUS = 20,
43 PD_CTRL_GET_COUNTRY_CODES = 21,
44 /* 22-31 Reserved */
38}; 45};
39 46
40enum pd_data_msg_type { 47enum pd_data_msg_type {
@@ -43,13 +50,39 @@ enum pd_data_msg_type {
43 PD_DATA_REQUEST = 2, 50 PD_DATA_REQUEST = 2,
44 PD_DATA_BIST = 3, 51 PD_DATA_BIST = 3,
45 PD_DATA_SINK_CAP = 4, 52 PD_DATA_SINK_CAP = 4,
46 /* 5-14 Reserved */ 53 PD_DATA_BATT_STATUS = 5,
54 PD_DATA_ALERT = 6,
55 PD_DATA_GET_COUNTRY_INFO = 7,
56 /* 8-14 Reserved */
47 PD_DATA_VENDOR_DEF = 15, 57 PD_DATA_VENDOR_DEF = 15,
58 /* 16-31 Reserved */
59};
60
61enum pd_ext_msg_type {
62 /* 0 Reserved */
63 PD_EXT_SOURCE_CAP_EXT = 1,
64 PD_EXT_STATUS = 2,
65 PD_EXT_GET_BATT_CAP = 3,
66 PD_EXT_GET_BATT_STATUS = 4,
67 PD_EXT_BATT_CAP = 5,
68 PD_EXT_GET_MANUFACTURER_INFO = 6,
69 PD_EXT_MANUFACTURER_INFO = 7,
70 PD_EXT_SECURITY_REQUEST = 8,
71 PD_EXT_SECURITY_RESPONSE = 9,
72 PD_EXT_FW_UPDATE_REQUEST = 10,
73 PD_EXT_FW_UPDATE_RESPONSE = 11,
74 PD_EXT_PPS_STATUS = 12,
75 PD_EXT_COUNTRY_INFO = 13,
76 PD_EXT_COUNTRY_CODES = 14,
77 /* 15-31 Reserved */
48}; 78};
49 79
50#define PD_REV10 0x0 80#define PD_REV10 0x0
51#define PD_REV20 0x1 81#define PD_REV20 0x1
82#define PD_REV30 0x2
83#define PD_MAX_REV PD_REV30
52 84
85#define PD_HEADER_EXT_HDR BIT(15)
53#define PD_HEADER_CNT_SHIFT 12 86#define PD_HEADER_CNT_SHIFT 12
54#define PD_HEADER_CNT_MASK 0x7 87#define PD_HEADER_CNT_MASK 0x7
55#define PD_HEADER_ID_SHIFT 9 88#define PD_HEADER_ID_SHIFT 9
@@ -59,18 +92,19 @@ enum pd_data_msg_type {
59#define PD_HEADER_REV_MASK 0x3 92#define PD_HEADER_REV_MASK 0x3
60#define PD_HEADER_DATA_ROLE BIT(5) 93#define PD_HEADER_DATA_ROLE BIT(5)
61#define PD_HEADER_TYPE_SHIFT 0 94#define PD_HEADER_TYPE_SHIFT 0
62#define PD_HEADER_TYPE_MASK 0xf 95#define PD_HEADER_TYPE_MASK 0x1f
63 96
64#define PD_HEADER(type, pwr, data, id, cnt) \ 97#define PD_HEADER(type, pwr, data, rev, id, cnt, ext_hdr) \
65 ((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \ 98 ((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \
66 ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \ 99 ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \
67 ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \ 100 ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \
68 (PD_REV20 << PD_HEADER_REV_SHIFT) | \ 101 (rev << PD_HEADER_REV_SHIFT) | \
69 (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \ 102 (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \
70 (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT)) 103 (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) | \
104 ((ext_hdr) ? PD_HEADER_EXT_HDR : 0))
71 105
72#define PD_HEADER_LE(type, pwr, data, id, cnt) \ 106#define PD_HEADER_LE(type, pwr, data, id, cnt) \
73 cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt))) 107 cpu_to_le16(PD_HEADER((type), (pwr), (data), PD_REV20, (id), (cnt), (0)))
74 108
75static inline unsigned int pd_header_cnt(u16 header) 109static inline unsigned int pd_header_cnt(u16 header)
76{ 110{
@@ -102,16 +136,75 @@ static inline unsigned int pd_header_msgid_le(__le16 header)
102 return pd_header_msgid(le16_to_cpu(header)); 136 return pd_header_msgid(le16_to_cpu(header));
103} 137}
104 138
139static inline unsigned int pd_header_rev(u16 header)
140{
141 return (header >> PD_HEADER_REV_SHIFT) & PD_HEADER_REV_MASK;
142}
143
144static inline unsigned int pd_header_rev_le(__le16 header)
145{
146 return pd_header_rev(le16_to_cpu(header));
147}
148
149#define PD_EXT_HDR_CHUNKED BIT(15)
150#define PD_EXT_HDR_CHUNK_NUM_SHIFT 11
151#define PD_EXT_HDR_CHUNK_NUM_MASK 0xf
152#define PD_EXT_HDR_REQ_CHUNK BIT(10)
153#define PD_EXT_HDR_DATA_SIZE_SHIFT 0
154#define PD_EXT_HDR_DATA_SIZE_MASK 0x1ff
155
156#define PD_EXT_HDR(data_size, req_chunk, chunk_num, chunked) \
157 ((((data_size) & PD_EXT_HDR_DATA_SIZE_MASK) << PD_EXT_HDR_DATA_SIZE_SHIFT) | \
158 ((req_chunk) ? PD_EXT_HDR_REQ_CHUNK : 0) | \
159 (((chunk_num) & PD_EXT_HDR_CHUNK_NUM_MASK) << PD_EXT_HDR_CHUNK_NUM_SHIFT) | \
160 ((chunked) ? PD_EXT_HDR_CHUNKED : 0))
161
162#define PD_EXT_HDR_LE(data_size, req_chunk, chunk_num, chunked) \
163 cpu_to_le16(PD_EXT_HDR((data_size), (req_chunk), (chunk_num), (chunked)))
164
165static inline unsigned int pd_ext_header_chunk_num(u16 ext_header)
166{
167 return (ext_header >> PD_EXT_HDR_CHUNK_NUM_SHIFT) &
168 PD_EXT_HDR_CHUNK_NUM_MASK;
169}
170
171static inline unsigned int pd_ext_header_data_size(u16 ext_header)
172{
173 return (ext_header >> PD_EXT_HDR_DATA_SIZE_SHIFT) &
174 PD_EXT_HDR_DATA_SIZE_MASK;
175}
176
177static inline unsigned int pd_ext_header_data_size_le(__le16 ext_header)
178{
179 return pd_ext_header_data_size(le16_to_cpu(ext_header));
180}
181
105#define PD_MAX_PAYLOAD 7 182#define PD_MAX_PAYLOAD 7
183#define PD_EXT_MAX_CHUNK_DATA 26
106 184
107/** 185/**
108 * struct pd_message - PD message as seen on wire 186 * struct pd_chunked_ext_message_data - PD chunked extended message data as
109 * @header: PD message header 187 * seen on wire
110 * @payload: PD message payload 188 * @header: PD extended message header
111 */ 189 * @data: PD extended message data
190 */
191struct pd_chunked_ext_message_data {
192 __le16 header;
193 u8 data[PD_EXT_MAX_CHUNK_DATA];
194} __packed;
195
196/**
197 * struct pd_message - PD message as seen on wire
198 * @header: PD message header
199 * @payload: PD message payload
200 * @ext_msg: PD message chunked extended message data
201 */
112struct pd_message { 202struct pd_message {
113 __le16 header; 203 __le16 header;
114 __le32 payload[PD_MAX_PAYLOAD]; 204 union {
205 __le32 payload[PD_MAX_PAYLOAD];
206 struct pd_chunked_ext_message_data ext_msg;
207 };
115} __packed; 208} __packed;
116 209
117/* PDO: Power Data Object */ 210/* PDO: Power Data Object */
@@ -121,6 +214,7 @@ enum pd_pdo_type {
121 PDO_TYPE_FIXED = 0, 214 PDO_TYPE_FIXED = 0,
122 PDO_TYPE_BATT = 1, 215 PDO_TYPE_BATT = 1,
123 PDO_TYPE_VAR = 2, 216 PDO_TYPE_VAR = 2,
217 PDO_TYPE_APDO = 3,
124}; 218};
125 219
126#define PDO_TYPE_SHIFT 30 220#define PDO_TYPE_SHIFT 30
@@ -174,6 +268,34 @@ enum pd_pdo_type {
174 (PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \ 268 (PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \
175 PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma)) 269 PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma))
176 270
271enum pd_apdo_type {
272 APDO_TYPE_PPS = 0,
273};
274
275#define PDO_APDO_TYPE_SHIFT 28 /* Only valid value currently is 0x0 - PPS */
276#define PDO_APDO_TYPE_MASK 0x3
277
278#define PDO_APDO_TYPE(t) ((t) << PDO_APDO_TYPE_SHIFT)
279
280#define PDO_PPS_APDO_MAX_VOLT_SHIFT 17 /* 100mV units */
281#define PDO_PPS_APDO_MIN_VOLT_SHIFT 8 /* 100mV units */
282#define PDO_PPS_APDO_MAX_CURR_SHIFT 0 /* 50mA units */
283
284#define PDO_PPS_APDO_VOLT_MASK 0xff
285#define PDO_PPS_APDO_CURR_MASK 0x7f
286
287#define PDO_PPS_APDO_MIN_VOLT(mv) \
288 ((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MIN_VOLT_SHIFT)
289#define PDO_PPS_APDO_MAX_VOLT(mv) \
290 ((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MAX_VOLT_SHIFT)
291#define PDO_PPS_APDO_MAX_CURR(ma) \
292 ((((ma) / 50) & PDO_PPS_APDO_CURR_MASK) << PDO_PPS_APDO_MAX_CURR_SHIFT)
293
294#define PDO_PPS_APDO(min_mv, max_mv, max_ma) \
295 (PDO_TYPE(PDO_TYPE_APDO) | PDO_APDO_TYPE(APDO_TYPE_PPS) | \
296 PDO_PPS_APDO_MIN_VOLT(min_mv) | PDO_PPS_APDO_MAX_VOLT(max_mv) | \
297 PDO_PPS_APDO_MAX_CURR(max_ma))
298
177static inline enum pd_pdo_type pdo_type(u32 pdo) 299static inline enum pd_pdo_type pdo_type(u32 pdo)
178{ 300{
179 return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK; 301 return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK;
@@ -204,6 +326,29 @@ static inline unsigned int pdo_max_power(u32 pdo)
204 return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250; 326 return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250;
205} 327}
206 328
329static inline enum pd_apdo_type pdo_apdo_type(u32 pdo)
330{
331 return (pdo >> PDO_APDO_TYPE_SHIFT) & PDO_APDO_TYPE_MASK;
332}
333
334static inline unsigned int pdo_pps_apdo_min_voltage(u32 pdo)
335{
336 return ((pdo >> PDO_PPS_APDO_MIN_VOLT_SHIFT) &
337 PDO_PPS_APDO_VOLT_MASK) * 100;
338}
339
340static inline unsigned int pdo_pps_apdo_max_voltage(u32 pdo)
341{
342 return ((pdo >> PDO_PPS_APDO_MAX_VOLT_SHIFT) &
343 PDO_PPS_APDO_VOLT_MASK) * 100;
344}
345
346static inline unsigned int pdo_pps_apdo_max_current(u32 pdo)
347{
348 return ((pdo >> PDO_PPS_APDO_MAX_CURR_SHIFT) &
349 PDO_PPS_APDO_CURR_MASK) * 50;
350}
351
207/* RDO: Request Data Object */ 352/* RDO: Request Data Object */
208#define RDO_OBJ_POS_SHIFT 28 353#define RDO_OBJ_POS_SHIFT 28
209#define RDO_OBJ_POS_MASK 0x7 354#define RDO_OBJ_POS_MASK 0x7
@@ -237,6 +382,24 @@ static inline unsigned int pdo_max_power(u32 pdo)
237 (RDO_OBJ(idx) | (flags) | \ 382 (RDO_OBJ(idx) | (flags) | \
238 RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw)) 383 RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw))
239 384
385#define RDO_PROG_VOLT_MASK 0x7ff
386#define RDO_PROG_CURR_MASK 0x7f
387
388#define RDO_PROG_VOLT_SHIFT 9
389#define RDO_PROG_CURR_SHIFT 0
390
391#define RDO_PROG_VOLT_MV_STEP 20
392#define RDO_PROG_CURR_MA_STEP 50
393
394#define PDO_PROG_OUT_VOLT(mv) \
395 ((((mv) / RDO_PROG_VOLT_MV_STEP) & RDO_PROG_VOLT_MASK) << RDO_PROG_VOLT_SHIFT)
396#define PDO_PROG_OP_CURR(ma) \
397 ((((ma) / RDO_PROG_CURR_MA_STEP) & RDO_PROG_CURR_MASK) << RDO_PROG_CURR_SHIFT)
398
399#define RDO_PROG(idx, out_mv, op_ma, flags) \
400 (RDO_OBJ(idx) | (flags) | \
401 PDO_PROG_OUT_VOLT(out_mv) | PDO_PROG_OP_CURR(op_ma))
402
240static inline unsigned int rdo_index(u32 rdo) 403static inline unsigned int rdo_index(u32 rdo)
241{ 404{
242 return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK; 405 return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK;
diff --git a/include/linux/usb/pd_ado.h b/include/linux/usb/pd_ado.h
new file mode 100644
index 000000000000..9aa1cf31c93c
--- /dev/null
+++ b/include/linux/usb/pd_ado.h
@@ -0,0 +1,42 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2017 Dialog Semiconductor
4 *
5 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
6 */
7
8#ifndef __LINUX_USB_PD_ADO_H
9#define __LINUX_USB_PD_ADO_H
10
11/* ADO : Alert Data Object */
12#define USB_PD_ADO_TYPE_SHIFT 24
13#define USB_PD_ADO_TYPE_MASK 0xff
14#define USB_PD_ADO_FIXED_BATT_SHIFT 20
15#define USB_PD_ADO_FIXED_BATT_MASK 0xf
16#define USB_PD_ADO_HOT_SWAP_BATT_SHIFT 16
17#define USB_PD_ADO_HOT_SWAP_BATT_MASK 0xf
18
19#define USB_PD_ADO_TYPE_BATT_STATUS_CHANGE BIT(1)
20#define USB_PD_ADO_TYPE_OCP BIT(2)
21#define USB_PD_ADO_TYPE_OTP BIT(3)
22#define USB_PD_ADO_TYPE_OP_COND_CHANGE BIT(4)
23#define USB_PD_ADO_TYPE_SRC_INPUT_CHANGE BIT(5)
24#define USB_PD_ADO_TYPE_OVP BIT(6)
25
26static inline unsigned int usb_pd_ado_type(u32 ado)
27{
28 return (ado >> USB_PD_ADO_TYPE_SHIFT) & USB_PD_ADO_TYPE_MASK;
29}
30
31static inline unsigned int usb_pd_ado_fixed_batt(u32 ado)
32{
33 return (ado >> USB_PD_ADO_FIXED_BATT_SHIFT) &
34 USB_PD_ADO_FIXED_BATT_MASK;
35}
36
37static inline unsigned int usb_pd_ado_hot_swap_batt(u32 ado)
38{
39 return (ado >> USB_PD_ADO_HOT_SWAP_BATT_SHIFT) &
40 USB_PD_ADO_HOT_SWAP_BATT_MASK;
41}
42#endif /* __LINUX_USB_PD_ADO_H */
diff --git a/include/linux/usb/pd_ext_sdb.h b/include/linux/usb/pd_ext_sdb.h
new file mode 100644
index 000000000000..0eb83ce19597
--- /dev/null
+++ b/include/linux/usb/pd_ext_sdb.h
@@ -0,0 +1,31 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2017 Dialog Semiconductor
4 *
5 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
6 */
7
8#ifndef __LINUX_USB_PD_EXT_SDB_H
9#define __LINUX_USB_PD_EXT_SDB_H
10
11/* SDB : Status Data Block */
12enum usb_pd_ext_sdb_fields {
13 USB_PD_EXT_SDB_INTERNAL_TEMP = 0,
14 USB_PD_EXT_SDB_PRESENT_INPUT,
15 USB_PD_EXT_SDB_PRESENT_BATT_INPUT,
16 USB_PD_EXT_SDB_EVENT_FLAGS,
17 USB_PD_EXT_SDB_TEMP_STATUS,
18 USB_PD_EXT_SDB_DATA_SIZE,
19};
20
21/* Event Flags */
22#define USB_PD_EXT_SDB_EVENT_OCP BIT(1)
23#define USB_PD_EXT_SDB_EVENT_OTP BIT(2)
24#define USB_PD_EXT_SDB_EVENT_OVP BIT(3)
25#define USB_PD_EXT_SDB_EVENT_CF_CV_MODE BIT(4)
26
27#define USB_PD_EXT_SDB_PPS_EVENTS (USB_PD_EXT_SDB_EVENT_OCP | \
28 USB_PD_EXT_SDB_EVENT_OTP | \
29 USB_PD_EXT_SDB_EVENT_OVP)
30
31#endif /* __LINUX_USB_PD_EXT_SDB_H */
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index f1fcec2fd5f8..b7a99ce56bc9 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -63,4 +63,7 @@
63 */ 63 */
64#define USB_QUIRK_DISCONNECT_SUSPEND BIT(12) 64#define USB_QUIRK_DISCONNECT_SUSPEND BIT(12)
65 65
66/* Device needs a pause after every control message. */
67#define USB_QUIRK_DELAY_CTRL_MSG BIT(13)
68
66#endif /* __LINUX_USB_QUIRKS_H */ 69#endif /* __LINUX_USB_QUIRKS_H */
diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h
new file mode 100644
index 000000000000..edc51be4a77c
--- /dev/null
+++ b/include/linux/usb/role.h
@@ -0,0 +1,53 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#ifndef __LINUX_USB_ROLE_H
4#define __LINUX_USB_ROLE_H
5
6#include <linux/device.h>
7
8struct usb_role_switch;
9
10enum usb_role {
11 USB_ROLE_NONE,
12 USB_ROLE_HOST,
13 USB_ROLE_DEVICE,
14};
15
16typedef int (*usb_role_switch_set_t)(struct device *dev, enum usb_role role);
17typedef enum usb_role (*usb_role_switch_get_t)(struct device *dev);
18
19/**
20 * struct usb_role_switch_desc - USB Role Switch Descriptor
21 * @usb2_port: Optional reference to the host controller port device (USB2)
22 * @usb3_port: Optional reference to the host controller port device (USB3)
23 * @udc: Optional reference to the peripheral controller device
24 * @set: Callback for setting the role
25 * @get: Callback for getting the role (optional)
26 * @allow_userspace_control: If true userspace may change the role through sysfs
27 *
28 * @usb2_port and @usb3_port will point to the USB host port and @udc to the USB
29 * device controller behind the USB connector with the role switch. If
30 * @usb2_port, @usb3_port and @udc are included in the description, the
31 * reference count for them should be incremented by the caller of
32 * usb_role_switch_register() before registering the switch.
33 */
34struct usb_role_switch_desc {
35 struct device *usb2_port;
36 struct device *usb3_port;
37 struct device *udc;
38 usb_role_switch_set_t set;
39 usb_role_switch_get_t get;
40 bool allow_userspace_control;
41};
42
43int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role);
44enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw);
45struct usb_role_switch *usb_role_switch_get(struct device *dev);
46void usb_role_switch_put(struct usb_role_switch *sw);
47
48struct usb_role_switch *
49usb_role_switch_register(struct device *parent,
50 const struct usb_role_switch_desc *desc);
51void usb_role_switch_unregister(struct usb_role_switch *sw);
52
53#endif /* __LINUX_USB_ROLE_H */
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h
index ca1c0b57f03f..f0d839daeaea 100644
--- a/include/linux/usb/tcpm.h
+++ b/include/linux/usb/tcpm.h
@@ -91,17 +91,13 @@ struct tcpc_config {
91 unsigned int operating_snk_mw; 91 unsigned int operating_snk_mw;
92 92
93 enum typec_port_type type; 93 enum typec_port_type type;
94 enum typec_port_data data;
94 enum typec_role default_role; 95 enum typec_role default_role;
95 bool try_role_hw; /* try.{src,snk} implemented in hardware */ 96 bool try_role_hw; /* try.{src,snk} implemented in hardware */
96 97
97 const struct typec_altmode_desc *alt_modes; 98 const struct typec_altmode_desc *alt_modes;
98}; 99};
99 100
100enum tcpc_usb_switch {
101 TCPC_USB_SWITCH_CONNECT,
102 TCPC_USB_SWITCH_DISCONNECT,
103};
104
105/* Mux state attributes */ 101/* Mux state attributes */
106#define TCPC_MUX_USB_ENABLED BIT(0) /* USB enabled */ 102#define TCPC_MUX_USB_ENABLED BIT(0) /* USB enabled */
107#define TCPC_MUX_DP_ENABLED BIT(1) /* DP enabled */ 103#define TCPC_MUX_DP_ENABLED BIT(1) /* DP enabled */
@@ -116,14 +112,6 @@ enum tcpc_mux_mode {
116 TCPC_MUX_DP_ENABLED, 112 TCPC_MUX_DP_ENABLED,
117}; 113};
118 114
119struct tcpc_mux_dev {
120 int (*set)(struct tcpc_mux_dev *dev, enum tcpc_mux_mode mux_mode,
121 enum tcpc_usb_switch usb_config,
122 enum typec_cc_polarity polarity);
123 bool dfp_only;
124 void *priv_data;
125};
126
127/** 115/**
128 * struct tcpc_dev - Port configuration and callback functions 116 * struct tcpc_dev - Port configuration and callback functions
129 * @config: Pointer to port configuration 117 * @config: Pointer to port configuration
@@ -175,7 +163,6 @@ struct tcpc_dev {
175 int (*try_role)(struct tcpc_dev *dev, int role); 163 int (*try_role)(struct tcpc_dev *dev, int role);
176 int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type, 164 int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type,
177 const struct pd_message *msg); 165 const struct pd_message *msg);
178 struct tcpc_mux_dev *mux;
179}; 166};
180 167
181struct tcpm_port; 168struct tcpm_port;
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 0d44ce6af08f..672b39bb0adc 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -22,9 +22,15 @@ struct typec_port;
22struct fwnode_handle; 22struct fwnode_handle;
23 23
24enum typec_port_type { 24enum typec_port_type {
25 TYPEC_PORT_SRC,
26 TYPEC_PORT_SNK,
27 TYPEC_PORT_DRP,
28};
29
30enum typec_port_data {
25 TYPEC_PORT_DFP, 31 TYPEC_PORT_DFP,
26 TYPEC_PORT_UFP, 32 TYPEC_PORT_UFP,
27 TYPEC_PORT_DRP, 33 TYPEC_PORT_DRD,
28}; 34};
29 35
30enum typec_plug_type { 36enum typec_plug_type {
@@ -60,6 +66,12 @@ enum typec_accessory {
60 66
61#define TYPEC_MAX_ACCESSORY 3 67#define TYPEC_MAX_ACCESSORY 3
62 68
69enum typec_orientation {
70 TYPEC_ORIENTATION_NONE,
71 TYPEC_ORIENTATION_NORMAL,
72 TYPEC_ORIENTATION_REVERSE,
73};
74
63/* 75/*
64 * struct usb_pd_identity - USB Power Delivery identity data 76 * struct usb_pd_identity - USB Power Delivery identity data
65 * @id_header: ID Header VDO 77 * @id_header: ID Header VDO
@@ -180,11 +192,14 @@ struct typec_partner_desc {
180 192
181/* 193/*
182 * struct typec_capability - USB Type-C Port Capabilities 194 * struct typec_capability - USB Type-C Port Capabilities
183 * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role) 195 * @type: Supported power role of the port
196 * @data: Supported data role of the port
184 * @revision: USB Type-C Specification release. Binary coded decimal 197 * @revision: USB Type-C Specification release. Binary coded decimal
185 * @pd_revision: USB Power Delivery Specification revision if supported 198 * @pd_revision: USB Power Delivery Specification revision if supported
186 * @prefer_role: Initial role preference 199 * @prefer_role: Initial role preference (DRP ports).
187 * @accessory: Supported Accessory Modes 200 * @accessory: Supported Accessory Modes
201 * @sw: Cable plug orientation switch
202 * @mux: Multiplexer switch for Alternate/Accessory Modes
188 * @fwnode: Optional fwnode of the port 203 * @fwnode: Optional fwnode of the port
189 * @try_role: Set data role preference for DRP port 204 * @try_role: Set data role preference for DRP port
190 * @dr_set: Set Data Role 205 * @dr_set: Set Data Role
@@ -197,11 +212,14 @@ struct typec_partner_desc {
197 */ 212 */
198struct typec_capability { 213struct typec_capability {
199 enum typec_port_type type; 214 enum typec_port_type type;
215 enum typec_port_data data;
200 u16 revision; /* 0120H = "1.2" */ 216 u16 revision; /* 0120H = "1.2" */
201 u16 pd_revision; /* 0300H = "3.0" */ 217 u16 pd_revision; /* 0300H = "3.0" */
202 int prefer_role; 218 int prefer_role;
203 enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; 219 enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];
204 220
221 struct typec_switch *sw;
222 struct typec_mux *mux;
205 struct fwnode_handle *fwnode; 223 struct fwnode_handle *fwnode;
206 224
207 int (*try_role)(const struct typec_capability *, 225 int (*try_role)(const struct typec_capability *,
@@ -245,4 +263,8 @@ void typec_set_pwr_role(struct typec_port *port, enum typec_role role);
245void typec_set_vconn_role(struct typec_port *port, enum typec_role role); 263void typec_set_vconn_role(struct typec_port *port, enum typec_role role);
246void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode); 264void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode);
247 265
266int typec_set_orientation(struct typec_port *port,
267 enum typec_orientation orientation);
268int typec_set_mode(struct typec_port *port, int mode);
269
248#endif /* __LINUX_USB_TYPEC_H */ 270#endif /* __LINUX_USB_TYPEC_H */
diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
new file mode 100644
index 000000000000..12c1b057834b
--- /dev/null
+++ b/include/linux/usb/typec_mux.h
@@ -0,0 +1,55 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#ifndef __USB_TYPEC_MUX
4#define __USB_TYPEC_MUX
5
6#include <linux/list.h>
7#include <linux/usb/typec.h>
8
9struct device;
10
11/**
12 * struct typec_switch - USB Type-C cable orientation switch
13 * @dev: Switch device
14 * @entry: List entry
15 * @set: Callback to the driver for setting the orientation
16 *
17 * USB Type-C pin flipper switch routing the correct data pairs from the
18 * connector to the USB controller depending on the orientation of the cable
19 * plug.
20 */
21struct typec_switch {
22 struct device *dev;
23 struct list_head entry;
24
25 int (*set)(struct typec_switch *sw, enum typec_orientation orientation);
26};
27
28/**
29 * struct typec_switch - USB Type-C connector pin mux
30 * @dev: Mux device
31 * @entry: List entry
32 * @set: Callback to the driver for setting the state of the mux
33 *
34 * Pin Multiplexer/DeMultiplexer switch routing the USB Type-C connector pins to
35 * different components depending on the requested mode of operation. Used with
36 * Accessory/Alternate modes.
37 */
38struct typec_mux {
39 struct device *dev;
40 struct list_head entry;
41
42 int (*set)(struct typec_mux *mux, int state);
43};
44
45struct typec_switch *typec_switch_get(struct device *dev);
46void typec_switch_put(struct typec_switch *sw);
47int typec_switch_register(struct typec_switch *sw);
48void typec_switch_unregister(struct typec_switch *sw);
49
50struct typec_mux *typec_mux_get(struct device *dev);
51void typec_mux_put(struct typec_mux *mux);
52int typec_mux_register(struct typec_mux *mux);
53void typec_mux_unregister(struct typec_mux *mux);
54
55#endif /* __USB_TYPEC_MUX */