xref: /linux-6.15/include/linux/usb/phy.h (revision bbb03029)
1 /*
2  * USB PHY defines
3  *
4  * These APIs may be used between USB controllers.  USB device drivers
5  * (for either host or peripheral roles) don't use these calls; they
6  * continue to use just usb_device and usb_gadget.
7  */
8 
9 #ifndef __LINUX_USB_PHY_H
10 #define __LINUX_USB_PHY_H
11 
12 #include <linux/extcon.h>
13 #include <linux/notifier.h>
14 #include <linux/usb.h>
15 
16 enum usb_phy_interface {
17 	USBPHY_INTERFACE_MODE_UNKNOWN,
18 	USBPHY_INTERFACE_MODE_UTMI,
19 	USBPHY_INTERFACE_MODE_UTMIW,
20 	USBPHY_INTERFACE_MODE_ULPI,
21 	USBPHY_INTERFACE_MODE_SERIAL,
22 	USBPHY_INTERFACE_MODE_HSIC,
23 };
24 
25 enum usb_phy_events {
26 	USB_EVENT_NONE,         /* no events or cable disconnected */
27 	USB_EVENT_VBUS,         /* vbus valid event */
28 	USB_EVENT_ID,           /* id was grounded */
29 	USB_EVENT_CHARGER,      /* usb dedicated charger */
30 	USB_EVENT_ENUMERATED,   /* gadget driver enumerated */
31 };
32 
33 /* associate a type with PHY */
34 enum usb_phy_type {
35 	USB_PHY_TYPE_UNDEFINED,
36 	USB_PHY_TYPE_USB2,
37 	USB_PHY_TYPE_USB3,
38 };
39 
40 /* OTG defines lots of enumeration states before device reset */
41 enum usb_otg_state {
42 	OTG_STATE_UNDEFINED = 0,
43 
44 	/* single-role peripheral, and dual-role default-b */
45 	OTG_STATE_B_IDLE,
46 	OTG_STATE_B_SRP_INIT,
47 	OTG_STATE_B_PERIPHERAL,
48 
49 	/* extra dual-role default-b states */
50 	OTG_STATE_B_WAIT_ACON,
51 	OTG_STATE_B_HOST,
52 
53 	/* dual-role default-a */
54 	OTG_STATE_A_IDLE,
55 	OTG_STATE_A_WAIT_VRISE,
56 	OTG_STATE_A_WAIT_BCON,
57 	OTG_STATE_A_HOST,
58 	OTG_STATE_A_SUSPEND,
59 	OTG_STATE_A_PERIPHERAL,
60 	OTG_STATE_A_WAIT_VFALL,
61 	OTG_STATE_A_VBUS_ERR,
62 };
63 
64 struct usb_phy;
65 struct usb_otg;
66 
67 /* for phys connected thru an ULPI interface, the user must
68  * provide access ops
69  */
70 struct usb_phy_io_ops {
71 	int (*read)(struct usb_phy *x, u32 reg);
72 	int (*write)(struct usb_phy *x, u32 val, u32 reg);
73 };
74 
75 struct usb_phy {
76 	struct device		*dev;
77 	const char		*label;
78 	unsigned int		 flags;
79 
80 	enum usb_phy_type	type;
81 	enum usb_phy_events	last_event;
82 
83 	struct usb_otg		*otg;
84 
85 	struct device		*io_dev;
86 	struct usb_phy_io_ops	*io_ops;
87 	void __iomem		*io_priv;
88 
89 	/* to support extcon device */
90 	struct extcon_dev	*edev;
91 	struct extcon_dev	*id_edev;
92 	struct notifier_block	vbus_nb;
93 	struct notifier_block	id_nb;
94 
95 	/* for notification of usb_phy_events */
96 	struct atomic_notifier_head	notifier;
97 
98 	/* to pass extra port status to the root hub */
99 	u16			port_status;
100 	u16			port_change;
101 
102 	/* to support controllers that have multiple phys */
103 	struct list_head	head;
104 
105 	/* initialize/shutdown the phy */
106 	int	(*init)(struct usb_phy *x);
107 	void	(*shutdown)(struct usb_phy *x);
108 
109 	/* enable/disable VBUS */
110 	int	(*set_vbus)(struct usb_phy *x, int on);
111 
112 	/* effective for B devices, ignored for A-peripheral */
113 	int	(*set_power)(struct usb_phy *x,
114 				unsigned mA);
115 
116 	/* Set phy into suspend mode */
117 	int	(*set_suspend)(struct usb_phy *x,
118 				int suspend);
119 
120 	/*
121 	 * Set wakeup enable for PHY, in that case, the PHY can be
122 	 * woken up from suspend status due to external events,
123 	 * like vbus change, dp/dm change and id.
124 	 */
125 	int	(*set_wakeup)(struct usb_phy *x, bool enabled);
126 
127 	/* notify phy connect status change */
128 	int	(*notify_connect)(struct usb_phy *x,
129 			enum usb_device_speed speed);
130 	int	(*notify_disconnect)(struct usb_phy *x,
131 			enum usb_device_speed speed);
132 };
133 
134 /**
135  * struct usb_phy_bind - represent the binding for the phy
136  * @dev_name: the device name of the device that will bind to the phy
137  * @phy_dev_name: the device name of the phy
138  * @index: used if a single controller uses multiple phys
139  * @phy: reference to the phy
140  * @list: to maintain a linked list of the binding information
141  */
142 struct usb_phy_bind {
143 	const char	*dev_name;
144 	const char	*phy_dev_name;
145 	u8		index;
146 	struct usb_phy	*phy;
147 	struct list_head list;
148 };
149 
150 /* for board-specific init logic */
151 extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
152 extern int usb_add_phy_dev(struct usb_phy *);
153 extern void usb_remove_phy(struct usb_phy *);
154 
155 /* helpers for direct access thru low-level io interface */
156 static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
157 {
158 	if (x && x->io_ops && x->io_ops->read)
159 		return x->io_ops->read(x, reg);
160 
161 	return -EINVAL;
162 }
163 
164 static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
165 {
166 	if (x && x->io_ops && x->io_ops->write)
167 		return x->io_ops->write(x, val, reg);
168 
169 	return -EINVAL;
170 }
171 
172 static inline int
173 usb_phy_init(struct usb_phy *x)
174 {
175 	if (x && x->init)
176 		return x->init(x);
177 
178 	return 0;
179 }
180 
181 static inline void
182 usb_phy_shutdown(struct usb_phy *x)
183 {
184 	if (x && x->shutdown)
185 		x->shutdown(x);
186 }
187 
188 static inline int
189 usb_phy_vbus_on(struct usb_phy *x)
190 {
191 	if (!x || !x->set_vbus)
192 		return 0;
193 
194 	return x->set_vbus(x, true);
195 }
196 
197 static inline int
198 usb_phy_vbus_off(struct usb_phy *x)
199 {
200 	if (!x || !x->set_vbus)
201 		return 0;
202 
203 	return x->set_vbus(x, false);
204 }
205 
206 /* for usb host and peripheral controller drivers */
207 #if IS_ENABLED(CONFIG_USB_PHY)
208 extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
209 extern struct usb_phy *devm_usb_get_phy(struct device *dev,
210 	enum usb_phy_type type);
211 extern struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index);
212 extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index);
213 extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
214 	const char *phandle, u8 index);
215 extern struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
216 	struct device_node *node, struct notifier_block *nb);
217 extern void usb_put_phy(struct usb_phy *);
218 extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
219 extern int usb_bind_phy(const char *dev_name, u8 index,
220 				const char *phy_dev_name);
221 extern void usb_phy_set_event(struct usb_phy *x, unsigned long event);
222 #else
223 static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
224 {
225 	return ERR_PTR(-ENXIO);
226 }
227 
228 static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
229 	enum usb_phy_type type)
230 {
231 	return ERR_PTR(-ENXIO);
232 }
233 
234 static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
235 {
236 	return ERR_PTR(-ENXIO);
237 }
238 
239 static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
240 {
241 	return ERR_PTR(-ENXIO);
242 }
243 
244 static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
245 	const char *phandle, u8 index)
246 {
247 	return ERR_PTR(-ENXIO);
248 }
249 
250 static inline struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
251 	struct device_node *node, struct notifier_block *nb)
252 {
253 	return ERR_PTR(-ENXIO);
254 }
255 
256 static inline void usb_put_phy(struct usb_phy *x)
257 {
258 }
259 
260 static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
261 {
262 }
263 
264 static inline int usb_bind_phy(const char *dev_name, u8 index,
265 				const char *phy_dev_name)
266 {
267 	return -EOPNOTSUPP;
268 }
269 
270 static inline void usb_phy_set_event(struct usb_phy *x, unsigned long event)
271 {
272 }
273 #endif
274 
275 static inline int
276 usb_phy_set_power(struct usb_phy *x, unsigned mA)
277 {
278 	if (x && x->set_power)
279 		return x->set_power(x, mA);
280 	return 0;
281 }
282 
283 /* Context: can sleep */
284 static inline int
285 usb_phy_set_suspend(struct usb_phy *x, int suspend)
286 {
287 	if (x && x->set_suspend != NULL)
288 		return x->set_suspend(x, suspend);
289 	else
290 		return 0;
291 }
292 
293 static inline int
294 usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
295 {
296 	if (x && x->set_wakeup)
297 		return x->set_wakeup(x, enabled);
298 	else
299 		return 0;
300 }
301 
302 static inline int
303 usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
304 {
305 	if (x && x->notify_connect)
306 		return x->notify_connect(x, speed);
307 	else
308 		return 0;
309 }
310 
311 static inline int
312 usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
313 {
314 	if (x && x->notify_disconnect)
315 		return x->notify_disconnect(x, speed);
316 	else
317 		return 0;
318 }
319 
320 /* notifiers */
321 static inline int
322 usb_register_notifier(struct usb_phy *x, struct notifier_block *nb)
323 {
324 	return atomic_notifier_chain_register(&x->notifier, nb);
325 }
326 
327 static inline void
328 usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
329 {
330 	atomic_notifier_chain_unregister(&x->notifier, nb);
331 }
332 
333 static inline const char *usb_phy_type_string(enum usb_phy_type type)
334 {
335 	switch (type) {
336 	case USB_PHY_TYPE_USB2:
337 		return "USB2 PHY";
338 	case USB_PHY_TYPE_USB3:
339 		return "USB3 PHY";
340 	default:
341 		return "UNKNOWN PHY TYPE";
342 	}
343 }
344 #endif /* __LINUX_USB_PHY_H */
345