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