1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | |
3 | #ifndef __LINUX_USB_TYPEC_H |
4 | #define __LINUX_USB_TYPEC_H |
5 | |
6 | #include <linux/types.h> |
7 | |
8 | /* USB Type-C Specification releases */ |
9 | #define USB_TYPEC_REV_1_0 0x100 /* 1.0 */ |
10 | #define USB_TYPEC_REV_1_1 0x110 /* 1.1 */ |
11 | #define USB_TYPEC_REV_1_2 0x120 /* 1.2 */ |
12 | #define USB_TYPEC_REV_1_3 0x130 /* 1.3 */ |
13 | #define USB_TYPEC_REV_1_4 0x140 /* 1.4 */ |
14 | #define USB_TYPEC_REV_2_0 0x200 /* 2.0 */ |
15 | |
16 | struct typec_partner; |
17 | struct typec_cable; |
18 | struct typec_plug; |
19 | struct typec_port; |
20 | struct typec_altmode_ops; |
21 | struct typec_cable_ops; |
22 | |
23 | struct fwnode_handle; |
24 | struct device; |
25 | |
26 | struct usb_power_delivery; |
27 | struct usb_power_delivery_desc; |
28 | |
29 | enum typec_port_type { |
30 | TYPEC_PORT_SRC, |
31 | TYPEC_PORT_SNK, |
32 | TYPEC_PORT_DRP, |
33 | }; |
34 | |
35 | enum typec_port_data { |
36 | TYPEC_PORT_DFP, |
37 | TYPEC_PORT_UFP, |
38 | TYPEC_PORT_DRD, |
39 | }; |
40 | |
41 | enum typec_plug_type { |
42 | USB_PLUG_NONE, |
43 | USB_PLUG_TYPE_A, |
44 | USB_PLUG_TYPE_B, |
45 | USB_PLUG_TYPE_C, |
46 | USB_PLUG_CAPTIVE, |
47 | }; |
48 | |
49 | enum typec_data_role { |
50 | TYPEC_DEVICE, |
51 | TYPEC_HOST, |
52 | }; |
53 | |
54 | enum typec_role { |
55 | TYPEC_SINK, |
56 | TYPEC_SOURCE, |
57 | }; |
58 | |
59 | static inline int is_sink(enum typec_role role) |
60 | { |
61 | return role == TYPEC_SINK; |
62 | } |
63 | |
64 | static inline int is_source(enum typec_role role) |
65 | { |
66 | return role == TYPEC_SOURCE; |
67 | } |
68 | |
69 | enum typec_pwr_opmode { |
70 | TYPEC_PWR_MODE_USB, |
71 | TYPEC_PWR_MODE_1_5A, |
72 | TYPEC_PWR_MODE_3_0A, |
73 | TYPEC_PWR_MODE_PD, |
74 | }; |
75 | |
76 | enum typec_accessory { |
77 | TYPEC_ACCESSORY_NONE, |
78 | TYPEC_ACCESSORY_AUDIO, |
79 | TYPEC_ACCESSORY_DEBUG, |
80 | }; |
81 | |
82 | #define TYPEC_MAX_ACCESSORY 3 |
83 | |
84 | enum typec_orientation { |
85 | TYPEC_ORIENTATION_NONE, |
86 | TYPEC_ORIENTATION_NORMAL, |
87 | TYPEC_ORIENTATION_REVERSE, |
88 | }; |
89 | |
90 | /* |
91 | * struct enter_usb_data - Enter_USB Message details |
92 | * @eudo: Enter_USB Data Object |
93 | * @active_link_training: Active Cable Plug Link Training |
94 | * |
95 | * @active_link_training is a flag that should be set with uni-directional SBRX |
96 | * communication, and left 0 with passive cables and with bi-directional SBRX |
97 | * communication. |
98 | */ |
99 | struct enter_usb_data { |
100 | u32 eudo; |
101 | unsigned char active_link_training:1; |
102 | }; |
103 | |
104 | /* |
105 | * struct usb_pd_identity - USB Power Delivery identity data |
106 | * @id_header: ID Header VDO |
107 | * @cert_stat: Cert Stat VDO |
108 | * @product: Product VDO |
109 | * @vdo: Product Type Specific VDOs |
110 | * |
111 | * USB power delivery Discover Identity command response data. |
112 | * |
113 | * REVISIT: This is USB Power Delivery specific information, so this structure |
114 | * probable belongs to USB Power Delivery header file once we have them. |
115 | */ |
116 | struct usb_pd_identity { |
117 | u32 ; |
118 | u32 cert_stat; |
119 | u32 product; |
120 | u32 vdo[3]; |
121 | }; |
122 | |
123 | int typec_partner_set_identity(struct typec_partner *partner); |
124 | int typec_cable_set_identity(struct typec_cable *cable); |
125 | |
126 | /* |
127 | * struct typec_altmode_desc - USB Type-C Alternate Mode Descriptor |
128 | * @svid: Standard or Vendor ID |
129 | * @mode: Index of the Mode |
130 | * @vdo: VDO returned by Discover Modes USB PD command |
131 | * @roles: Only for ports. DRP if the mode is available in both roles |
132 | * |
133 | * Description of an Alternate Mode which a connector, cable plug or partner |
134 | * supports. |
135 | */ |
136 | struct typec_altmode_desc { |
137 | u16 svid; |
138 | u8 mode; |
139 | u32 vdo; |
140 | /* Only used with ports */ |
141 | enum typec_port_data roles; |
142 | }; |
143 | |
144 | void typec_partner_set_pd_revision(struct typec_partner *partner, u16 pd_revision); |
145 | int typec_partner_set_num_altmodes(struct typec_partner *partner, int num_altmodes); |
146 | struct typec_altmode |
147 | *typec_partner_register_altmode(struct typec_partner *partner, |
148 | const struct typec_altmode_desc *desc); |
149 | int typec_plug_set_num_altmodes(struct typec_plug *plug, int num_altmodes); |
150 | struct typec_altmode |
151 | *typec_plug_register_altmode(struct typec_plug *plug, |
152 | const struct typec_altmode_desc *desc); |
153 | struct typec_altmode |
154 | *typec_port_register_altmode(struct typec_port *port, |
155 | const struct typec_altmode_desc *desc); |
156 | |
157 | void typec_port_register_altmodes(struct typec_port *port, |
158 | const struct typec_altmode_ops *ops, void *drvdata, |
159 | struct typec_altmode **altmodes, size_t n); |
160 | |
161 | void typec_port_register_cable_ops(struct typec_altmode **altmodes, int max_altmodes, |
162 | const struct typec_cable_ops *ops); |
163 | |
164 | void typec_unregister_altmode(struct typec_altmode *altmode); |
165 | |
166 | struct typec_port *typec_altmode2port(struct typec_altmode *alt); |
167 | |
168 | void typec_altmode_update_active(struct typec_altmode *alt, bool active); |
169 | |
170 | enum typec_plug_index { |
171 | TYPEC_PLUG_SOP_P, |
172 | TYPEC_PLUG_SOP_PP, |
173 | }; |
174 | |
175 | /* |
176 | * struct typec_plug_desc - USB Type-C Cable Plug Descriptor |
177 | * @index: SOP Prime for the plug connected to DFP and SOP Double Prime for the |
178 | * plug connected to UFP |
179 | * |
180 | * Represents USB Type-C Cable Plug. |
181 | */ |
182 | struct typec_plug_desc { |
183 | enum typec_plug_index index; |
184 | }; |
185 | |
186 | /* |
187 | * struct typec_cable_desc - USB Type-C Cable Descriptor |
188 | * @type: The plug type from USB PD Cable VDO |
189 | * @active: Is the cable active or passive |
190 | * @identity: Result of Discover Identity command |
191 | * @pd_revision: USB Power Delivery Specification revision if supported |
192 | * |
193 | * Represents USB Type-C Cable attached to USB Type-C port. |
194 | */ |
195 | struct typec_cable_desc { |
196 | enum typec_plug_type type; |
197 | unsigned int active:1; |
198 | struct usb_pd_identity *identity; |
199 | u16 pd_revision; /* 0300H = "3.0" */ |
200 | |
201 | }; |
202 | |
203 | /* |
204 | * struct typec_partner_desc - USB Type-C Partner Descriptor |
205 | * @usb_pd: USB Power Delivery support |
206 | * @accessory: Audio, Debug or none. |
207 | * @identity: Discover Identity command data |
208 | * @pd_revision: USB Power Delivery Specification Revision if supported |
209 | * @attach: Notification about attached USB device |
210 | * @deattach: Notification about removed USB device |
211 | * |
212 | * Details about a partner that is attached to USB Type-C port. If @identity |
213 | * member exists when partner is registered, a directory named "identity" is |
214 | * created to sysfs for the partner device. |
215 | * |
216 | * @pd_revision is based on the setting of the "Specification Revision" field |
217 | * in the message header on the initial "Source Capabilities" message received |
218 | * from the partner, or a "Request" message received from the partner, depending |
219 | * on whether our port is a Sink or a Source. |
220 | */ |
221 | struct typec_partner_desc { |
222 | unsigned int usb_pd:1; |
223 | enum typec_accessory accessory; |
224 | struct usb_pd_identity *identity; |
225 | u16 pd_revision; /* 0300H = "3.0" */ |
226 | |
227 | void (*attach)(struct typec_partner *partner, struct device *dev); |
228 | void (*deattach)(struct typec_partner *partner, struct device *dev); |
229 | }; |
230 | |
231 | /** |
232 | * struct typec_operations - USB Type-C Port Operations |
233 | * @try_role: Set data role preference for DRP port |
234 | * @dr_set: Set Data Role |
235 | * @pr_set: Set Power Role |
236 | * @vconn_set: Source VCONN |
237 | * @port_type_set: Set port type |
238 | * @pd_get: Get available USB Power Delivery Capabilities. |
239 | * @pd_set: Set USB Power Delivery Capabilities. |
240 | */ |
241 | struct typec_operations { |
242 | int (*try_role)(struct typec_port *port, int role); |
243 | int (*dr_set)(struct typec_port *port, enum typec_data_role role); |
244 | int (*pr_set)(struct typec_port *port, enum typec_role role); |
245 | int (*vconn_set)(struct typec_port *port, enum typec_role role); |
246 | int (*port_type_set)(struct typec_port *port, |
247 | enum typec_port_type type); |
248 | struct usb_power_delivery **(*pd_get)(struct typec_port *port); |
249 | int (*pd_set)(struct typec_port *port, struct usb_power_delivery *pd); |
250 | }; |
251 | |
252 | enum usb_pd_svdm_ver { |
253 | SVDM_VER_1_0 = 0, |
254 | SVDM_VER_2_0 = 1, |
255 | SVDM_VER_MAX = SVDM_VER_2_0, |
256 | }; |
257 | |
258 | /* |
259 | * struct typec_capability - USB Type-C Port Capabilities |
260 | * @type: Supported power role of the port |
261 | * @data: Supported data role of the port |
262 | * @revision: USB Type-C Specification release. Binary coded decimal |
263 | * @pd_revision: USB Power Delivery Specification revision if supported |
264 | * @svdm_version: USB PD Structured VDM version if supported |
265 | * @prefer_role: Initial role preference (DRP ports). |
266 | * @accessory: Supported Accessory Modes |
267 | * @fwnode: Optional fwnode of the port |
268 | * @driver_data: Private pointer for driver specific info |
269 | * @pd: Optional USB Power Delivery Support |
270 | * @ops: Port operations vector |
271 | * |
272 | * Static capabilities of a single USB Type-C port. |
273 | */ |
274 | struct typec_capability { |
275 | enum typec_port_type type; |
276 | enum typec_port_data data; |
277 | u16 revision; /* 0120H = "1.2" */ |
278 | u16 pd_revision; /* 0300H = "3.0" */ |
279 | enum usb_pd_svdm_ver svdm_version; |
280 | int prefer_role; |
281 | enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; |
282 | unsigned int orientation_aware:1; |
283 | |
284 | struct fwnode_handle *fwnode; |
285 | void *driver_data; |
286 | |
287 | struct usb_power_delivery *pd; |
288 | |
289 | const struct typec_operations *ops; |
290 | }; |
291 | |
292 | /* Specific to try_role(). Indicates the user want's to clear the preference. */ |
293 | #define TYPEC_NO_PREFERRED_ROLE (-1) |
294 | |
295 | struct typec_port *typec_register_port(struct device *parent, |
296 | const struct typec_capability *cap); |
297 | void typec_unregister_port(struct typec_port *port); |
298 | |
299 | struct typec_partner *typec_register_partner(struct typec_port *port, |
300 | struct typec_partner_desc *desc); |
301 | void typec_unregister_partner(struct typec_partner *partner); |
302 | |
303 | struct typec_cable *typec_register_cable(struct typec_port *port, |
304 | struct typec_cable_desc *desc); |
305 | void typec_unregister_cable(struct typec_cable *cable); |
306 | |
307 | struct typec_cable *typec_cable_get(struct typec_port *port); |
308 | void typec_cable_put(struct typec_cable *cable); |
309 | int typec_cable_is_active(struct typec_cable *cable); |
310 | |
311 | struct typec_plug *typec_register_plug(struct typec_cable *cable, |
312 | struct typec_plug_desc *desc); |
313 | void typec_unregister_plug(struct typec_plug *plug); |
314 | |
315 | void typec_set_data_role(struct typec_port *port, enum typec_data_role role); |
316 | void typec_set_pwr_role(struct typec_port *port, enum typec_role role); |
317 | void typec_set_vconn_role(struct typec_port *port, enum typec_role role); |
318 | void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode); |
319 | |
320 | int typec_set_orientation(struct typec_port *port, |
321 | enum typec_orientation orientation); |
322 | enum typec_orientation typec_get_orientation(struct typec_port *port); |
323 | int typec_set_mode(struct typec_port *port, int mode); |
324 | |
325 | void *typec_get_drvdata(struct typec_port *port); |
326 | |
327 | int typec_get_fw_cap(struct typec_capability *cap, |
328 | struct fwnode_handle *fwnode); |
329 | |
330 | int typec_find_pwr_opmode(const char *name); |
331 | int typec_find_orientation(const char *name); |
332 | int typec_find_port_power_role(const char *name); |
333 | int typec_find_power_role(const char *name); |
334 | int typec_find_port_data_role(const char *name); |
335 | |
336 | void typec_partner_set_svdm_version(struct typec_partner *partner, |
337 | enum usb_pd_svdm_ver svdm_version); |
338 | int typec_get_negotiated_svdm_version(struct typec_port *port); |
339 | |
340 | int typec_get_cable_svdm_version(struct typec_port *port); |
341 | void typec_cable_set_svdm_version(struct typec_cable *cable, enum usb_pd_svdm_ver svdm_version); |
342 | |
343 | struct usb_power_delivery *typec_partner_usb_power_delivery_register(struct typec_partner *partner, |
344 | struct usb_power_delivery_desc *desc); |
345 | |
346 | int typec_port_set_usb_power_delivery(struct typec_port *port, struct usb_power_delivery *pd); |
347 | int typec_partner_set_usb_power_delivery(struct typec_partner *partner, |
348 | struct usb_power_delivery *pd); |
349 | |
350 | /** |
351 | * struct typec_connector - Representation of Type-C port for external drivers |
352 | * @attach: notification about device removal |
353 | * @deattach: notification about device removal |
354 | * |
355 | * Drivers that control the USB and other ports (DisplayPorts, etc.), that are |
356 | * connected to the Type-C connectors, can use these callbacks to inform the |
357 | * Type-C connector class about connections and disconnections. That information |
358 | * can then be used by the typec-port drivers to power on or off parts that are |
359 | * needed or not needed - as an example, in USB mode if USB2 device is |
360 | * enumerated, USB3 components (retimers, phys, and what have you) do not need |
361 | * to be powered on. |
362 | * |
363 | * The attached (enumerated) devices will be liked with the typec-partner device. |
364 | */ |
365 | struct typec_connector { |
366 | void (*attach)(struct typec_connector *con, struct device *dev); |
367 | void (*deattach)(struct typec_connector *con, struct device *dev); |
368 | }; |
369 | |
370 | static inline void typec_attach(struct typec_connector *con, struct device *dev) |
371 | { |
372 | if (con && con->attach) |
373 | con->attach(con, dev); |
374 | } |
375 | |
376 | static inline void typec_deattach(struct typec_connector *con, struct device *dev) |
377 | { |
378 | if (con && con->deattach) |
379 | con->deattach(con, dev); |
380 | } |
381 | |
382 | #endif /* __LINUX_USB_TYPEC_H */ |
383 | |