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 };
34 
35 #define to_typec_altmode(d) container_of(d, struct typec_altmode, dev)
36 
typec_altmode_set_drvdata(struct typec_altmode * altmode,void * data)37 static inline void typec_altmode_set_drvdata(struct typec_altmode *altmode,
38 					     void *data)
39 {
40 	dev_set_drvdata(&altmode->dev, data);
41 }
42 
typec_altmode_get_drvdata(struct typec_altmode * altmode)43 static inline void *typec_altmode_get_drvdata(struct typec_altmode *altmode)
44 {
45 	return dev_get_drvdata(&altmode->dev);
46 }
47 
48 /**
49  * struct typec_altmode_ops - Alternate mode specific operations vector
50  * @enter: Operations to be executed with Enter Mode Command
51  * @exit: Operations to be executed with Exit Mode Command
52  * @attention: Callback for Attention Command
53  * @vdm: Callback for SVID specific commands
54  * @notify: Communication channel for platform and the alternate mode
55  * @activate: User callback for Enter/Exit Mode
56  */
57 struct typec_altmode_ops {
58 	int (*enter)(struct typec_altmode *altmode);
59 	int (*exit)(struct typec_altmode *altmode);
60 	void (*attention)(struct typec_altmode *altmode, u32 vdo);
61 	int (*vdm)(struct typec_altmode *altmode, const u32 hdr,
62 		   const u32 *vdo, int cnt);
63 	int (*notify)(struct typec_altmode *altmode, unsigned long conf,
64 		      void *data);
65 	int (*activate)(struct typec_altmode *altmode, int activate);
66 };
67 
68 int typec_altmode_enter(struct typec_altmode *altmode);
69 int typec_altmode_exit(struct typec_altmode *altmode);
70 void typec_altmode_attention(struct typec_altmode *altmode, u32 vdo);
71 int typec_altmode_vdm(struct typec_altmode *altmode,
72 		      const u32 header, const u32 *vdo, int count);
73 int typec_altmode_notify(struct typec_altmode *altmode, unsigned long conf,
74 			 void *data);
75 const struct typec_altmode *
76 typec_altmode_get_partner(struct typec_altmode *altmode);
77 
78 /*
79  * These are the connector states (USB, Safe and Alt Mode) defined in USB Type-C
80  * Specification. SVID specific connector states are expected to follow and
81  * start from the value TYPEC_STATE_MODAL.
82  */
83 enum {
84 	TYPEC_STATE_SAFE,	/* USB Safe State */
85 	TYPEC_STATE_USB,	/* USB Operation */
86 	TYPEC_STATE_MODAL,	/* Alternate Modes */
87 };
88 
89 /*
90  * For the muxes there is no difference between Accessory Modes and Alternate
91  * Modes, so the Accessory Modes are supplied with specific modal state values
92  * here. Unlike with Alternate Modes, where the mux will be linked with the
93  * alternate mode device, the mux for Accessory Modes will be linked with the
94  * port device instead.
95  *
96  * Port drivers can use TYPEC_MODE_AUDIO and TYPEC_MODE_DEBUG as the mode
97  * value for typec_set_mode() when accessory modes are supported.
98  */
99 enum {
100 	TYPEC_MODE_AUDIO = TYPEC_STATE_MODAL,	/* Audio Accessory */
101 	TYPEC_MODE_DEBUG,			/* Debug Accessory */
102 };
103 
104 #define TYPEC_MODAL_STATE(_state_)	((_state_) + TYPEC_STATE_MODAL)
105 
106 struct typec_altmode *typec_altmode_get_plug(struct typec_altmode *altmode,
107 					     enum typec_plug_index index);
108 void typec_altmode_put_plug(struct typec_altmode *plug);
109 
110 struct typec_altmode *typec_match_altmode(struct typec_altmode **altmodes,
111 					  size_t n, u16 svid, u8 mode);
112 
113 struct typec_altmode *
114 typec_altmode_register_notifier(struct device *dev, u16 svid, u8 mode,
115 				struct notifier_block *nb);
116 
117 void typec_altmode_unregister_notifier(struct typec_altmode *adev,
118 				       struct notifier_block *nb);
119 
120 /**
121  * typec_altmode_get_orientation - Get cable plug orientation
122  * altmode: Handle to the alternate mode
123  */
124 static inline enum typec_orientation
typec_altmode_get_orientation(struct typec_altmode * altmode)125 typec_altmode_get_orientation(struct typec_altmode *altmode)
126 {
127 	return typec_get_orientation(typec_altmode2port(altmode));
128 }
129 
130 /**
131  * struct typec_altmode_driver - USB Type-C alternate mode device driver
132  * @id_table: Null terminated array of SVIDs
133  * @probe: Callback for device binding
134  * @remove: Callback for device unbinding
135  * @driver: Device driver model driver
136  *
137  * These drivers will be bind to the partner alternate mode devices. They will
138  * handle all SVID specific communication.
139  */
140 struct typec_altmode_driver {
141 	const struct typec_device_id *id_table;
142 	int (*probe)(struct typec_altmode *altmode);
143 	void (*remove)(struct typec_altmode *altmode);
144 	struct device_driver driver;
145 };
146 
147 #define to_altmode_driver(d) container_of(d, struct typec_altmode_driver, \
148 					  driver)
149 
150 #define typec_altmode_register_driver(drv) \
151 		__typec_altmode_register_driver(drv, THIS_MODULE)
152 int __typec_altmode_register_driver(struct typec_altmode_driver *drv,
153 				    struct module *module);
154 void typec_altmode_unregister_driver(struct typec_altmode_driver *drv);
155 
156 #define module_typec_altmode_driver(__typec_altmode_driver) \
157 	module_driver(__typec_altmode_driver, typec_altmode_register_driver, \
158 		      typec_altmode_unregister_driver)
159 
160 #endif /* __USB_TYPEC_ALTMODE_H */
161