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