• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 #ifndef __USB_TYPEC_ALTMODE_H
4 #define __USB_TYPEC_ALTMODE_H
5 
6 #include <linux/mod_devicetable.h>
7 #include <linux/usb/typec.h>
8 #include <linux/device.h>
9 
10 #define MODE_DISCOVERY_MAX	6
11 
12 struct typec_altmode_ops;
13 
14 /**
15  * struct typec_altmode - USB Type-C alternate mode device
16  * @dev: Driver model's view of this device
17  * @svid: Standard or Vendor ID (SVID) of the alternate mode
18  * @mode: Index of the Mode
19  * @vdo: VDO returned by Discover Modes USB PD command
20  * @active: Tells has the mode been entered or not
21  * @desc: Optional human readable description of the mode
22  * @ops: Operations vector from the driver
23  * @cable_ops: Cable operations vector from the driver.
24  */
25 struct typec_altmode {
26 	struct device			dev;
27 	u16				svid;
28 	int				mode;
29 	u32				vdo;
30 	unsigned int			active:1;
31 
32 	char				*desc;
33 	const struct typec_altmode_ops	*ops;
34 	const struct typec_cable_ops	*cable_ops;
35 	ANDROID_KABI_RESERVE(1);
36 };
37 
38 #define to_typec_altmode(d) container_of(d, struct typec_altmode, dev)
39 
typec_altmode_set_drvdata(struct typec_altmode * altmode,void * data)40 static inline void typec_altmode_set_drvdata(struct typec_altmode *altmode,
41 					     void *data)
42 {
43 	dev_set_drvdata(&altmode->dev, data);
44 }
45 
typec_altmode_get_drvdata(struct typec_altmode * altmode)46 static inline void *typec_altmode_get_drvdata(struct typec_altmode *altmode)
47 {
48 	return dev_get_drvdata(&altmode->dev);
49 }
50 
51 /**
52  * struct typec_altmode_ops - Alternate mode specific operations vector
53  * @enter: Operations to be executed with Enter Mode Command
54  * @exit: Operations to be executed with Exit Mode Command
55  * @attention: Callback for Attention Command
56  * @vdm: Callback for SVID specific commands
57  * @notify: Communication channel for platform and the alternate mode
58  * @activate: User callback for Enter/Exit Mode
59  */
60 struct typec_altmode_ops {
61 	int (*enter)(struct typec_altmode *altmode, u32 *vdo);
62 	int (*exit)(struct typec_altmode *altmode);
63 	void (*attention)(struct typec_altmode *altmode, u32 vdo);
64 	int (*vdm)(struct typec_altmode *altmode, const u32 hdr,
65 		   const u32 *vdo, int cnt);
66 	int (*notify)(struct typec_altmode *altmode, unsigned long conf,
67 		      void *data);
68 	int (*activate)(struct typec_altmode *altmode, int activate);
69 	ANDROID_KABI_RESERVE(1);
70 };
71 
72 int typec_altmode_enter(struct typec_altmode *altmode, u32 *vdo);
73 int typec_altmode_exit(struct typec_altmode *altmode);
74 int typec_altmode_attention(struct typec_altmode *altmode, u32 vdo);
75 int typec_altmode_vdm(struct typec_altmode *altmode,
76 		      const u32 header, const u32 *vdo, int count);
77 int typec_altmode_notify(struct typec_altmode *altmode, unsigned long conf,
78 			 void *data);
79 const struct typec_altmode *
80 typec_altmode_get_partner(struct typec_altmode *altmode);
81 
82 /**
83  * struct typec_cable_ops - Cable alternate mode operations vector
84  * @enter: Operations to be executed with Enter Mode Command
85  * @exit: Operations to be executed with Exit Mode Command
86  * @vdm: Callback for SVID specific commands
87  */
88 struct typec_cable_ops {
89 	int (*enter)(struct typec_altmode *altmode, enum typec_plug_index sop, u32 *vdo);
90 	int (*exit)(struct typec_altmode *altmode, enum typec_plug_index sop);
91 	int (*vdm)(struct typec_altmode *altmode, enum typec_plug_index sop,
92 		   const u32 hdr, const u32 *vdo, int cnt);
93 };
94 
95 int typec_cable_altmode_enter(struct typec_altmode *altmode, enum typec_plug_index sop, u32 *vdo);
96 int typec_cable_altmode_exit(struct typec_altmode *altmode, enum typec_plug_index sop);
97 int typec_cable_altmode_vdm(struct typec_altmode *altmode, enum typec_plug_index sop,
98 			    const u32 header, const u32 *vdo, int count);
99 
100 /**
101  * typec_altmode_get_cable_svdm_version - Get negotiated SVDM version for cable plug
102  * @altmode: Handle to the alternate mode
103  */
104 static inline int
typec_altmode_get_cable_svdm_version(struct typec_altmode * altmode)105 typec_altmode_get_cable_svdm_version(struct typec_altmode *altmode)
106 {
107 	return typec_get_cable_svdm_version(typec_altmode2port(altmode));
108 }
109 
110 /*
111  * These are the connector states (USB, Safe and Alt Mode) defined in USB Type-C
112  * Specification. SVID specific connector states are expected to follow and
113  * start from the value TYPEC_STATE_MODAL.
114  */
115 enum {
116 	TYPEC_STATE_SAFE,	/* USB Safe State */
117 	TYPEC_STATE_USB,	/* USB Operation */
118 	TYPEC_STATE_MODAL,	/* Alternate Modes */
119 };
120 
121 /*
122  * For the muxes there is no difference between Accessory Modes and Alternate
123  * Modes, so the Accessory Modes are supplied with specific modal state values
124  * here. Unlike with Alternate Modes, where the mux will be linked with the
125  * alternate mode device, the mux for Accessory Modes will be linked with the
126  * port device instead.
127  *
128  * Port drivers can use TYPEC_MODE_AUDIO and TYPEC_MODE_DEBUG as the mode
129  * value for typec_set_mode() when accessory modes are supported.
130  *
131  * USB4 also requires that the pins on the connector are repurposed, just like
132  * Alternate Modes. USB4 mode is however not entered with the Enter Mode Command
133  * like the Alternate Modes are, but instead with a special Enter_USB Message.
134  * The Enter_USB Message can also be used for setting to connector to operate in
135  * USB 3.2 or in USB 2.0 mode instead of USB4.
136  *
137  * The Enter_USB specific "USB Modes" are also supplied here as special modal
138  * state values, just like the Accessory Modes.
139  */
140 enum {
141 	TYPEC_MODE_USB2 = TYPEC_STATE_MODAL,	/* USB 2.0 mode */
142 	TYPEC_MODE_USB3,			/* USB 3.2 mode */
143 	TYPEC_MODE_USB4,			/* USB4 mode */
144 	TYPEC_MODE_AUDIO,			/* Audio Accessory */
145 	TYPEC_MODE_DEBUG,			/* Debug Accessory */
146 };
147 
148 #define TYPEC_MODAL_STATE(_state_)	((_state_) + TYPEC_STATE_MODAL)
149 
150 struct typec_altmode *typec_altmode_get_plug(struct typec_altmode *altmode,
151 					     enum typec_plug_index index);
152 void typec_altmode_put_plug(struct typec_altmode *plug);
153 
154 struct typec_altmode *typec_match_altmode(struct typec_altmode **altmodes,
155 					  size_t n, u16 svid, u8 mode);
156 
157 /**
158  * typec_altmode_get_orientation - Get cable plug orientation
159  * @altmode: Handle to the alternate mode
160  */
161 static inline enum typec_orientation
typec_altmode_get_orientation(struct typec_altmode * altmode)162 typec_altmode_get_orientation(struct typec_altmode *altmode)
163 {
164 	return typec_get_orientation(typec_altmode2port(altmode));
165 }
166 
167 /**
168  * typec_altmode_get_svdm_version - Get negotiated SVDM version
169  * @altmode: Handle to the alternate mode
170  */
171 static inline int
typec_altmode_get_svdm_version(struct typec_altmode * altmode)172 typec_altmode_get_svdm_version(struct typec_altmode *altmode)
173 {
174 	return typec_get_negotiated_svdm_version(typec_altmode2port(altmode));
175 }
176 
177 /**
178  * struct typec_altmode_driver - USB Type-C alternate mode device driver
179  * @id_table: Null terminated array of SVIDs
180  * @probe: Callback for device binding
181  * @remove: Callback for device unbinding
182  * @driver: Device driver model driver
183  *
184  * These drivers will be bind to the partner alternate mode devices. They will
185  * handle all SVID specific communication.
186  */
187 struct typec_altmode_driver {
188 	const struct typec_device_id *id_table;
189 	int (*probe)(struct typec_altmode *altmode);
190 	void (*remove)(struct typec_altmode *altmode);
191 	struct device_driver driver;
192 };
193 
194 #define to_altmode_driver(d) container_of(d, struct typec_altmode_driver, \
195 					  driver)
196 
197 /**
198  * typec_altmode_register_driver - registers a USB Type-C alternate mode
199  * 				   device driver
200  * @drv: pointer to struct typec_altmode_driver
201  *
202  * These drivers will be bind to the partner alternate mode devices. They will
203  * handle all SVID specific communication.
204  */
205 #define typec_altmode_register_driver(drv) \
206 		__typec_altmode_register_driver(drv, THIS_MODULE)
207 int __typec_altmode_register_driver(struct typec_altmode_driver *drv,
208 				    struct module *module);
209 /**
210  * typec_altmode_unregister_driver - unregisters a USB Type-C alternate mode
211  * 				     device driver
212  * @drv: pointer to struct typec_altmode_driver
213  *
214  * These drivers will be bind to the partner alternate mode devices. They will
215  * handle all SVID specific communication.
216  */
217 void typec_altmode_unregister_driver(struct typec_altmode_driver *drv);
218 
219 #define module_typec_altmode_driver(__typec_altmode_driver) \
220 	module_driver(__typec_altmode_driver, typec_altmode_register_driver, \
221 		      typec_altmode_unregister_driver)
222 
223 #endif /* __USB_TYPEC_ALTMODE_H */
224