1fde0aa6cSHeikki Krogerus // SPDX-License-Identifier: GPL-2.0
2fde0aa6cSHeikki Krogerus
3fde0aa6cSHeikki Krogerus #ifndef __LINUX_USB_ROLE_H
4fde0aa6cSHeikki Krogerus #define __LINUX_USB_ROLE_H
5fde0aa6cSHeikki Krogerus
6fde0aa6cSHeikki Krogerus #include <linux/device.h>
7fde0aa6cSHeikki Krogerus
8fde0aa6cSHeikki Krogerus struct usb_role_switch;
9fde0aa6cSHeikki Krogerus
10fde0aa6cSHeikki Krogerus enum usb_role {
11fde0aa6cSHeikki Krogerus USB_ROLE_NONE,
12fde0aa6cSHeikki Krogerus USB_ROLE_HOST,
13fde0aa6cSHeikki Krogerus USB_ROLE_DEVICE,
14fde0aa6cSHeikki Krogerus };
15fde0aa6cSHeikki Krogerus
16bce3052fSHeikki Krogerus typedef int (*usb_role_switch_set_t)(struct usb_role_switch *sw,
17bce3052fSHeikki Krogerus enum usb_role role);
18bce3052fSHeikki Krogerus typedef enum usb_role (*usb_role_switch_get_t)(struct usb_role_switch *sw);
19fde0aa6cSHeikki Krogerus
20fde0aa6cSHeikki Krogerus /**
21fde0aa6cSHeikki Krogerus * struct usb_role_switch_desc - USB Role Switch Descriptor
22ec69e953SHeikki Krogerus * @fwnode: The device node to be associated with the role switch
23fde0aa6cSHeikki Krogerus * @usb2_port: Optional reference to the host controller port device (USB2)
24fde0aa6cSHeikki Krogerus * @usb3_port: Optional reference to the host controller port device (USB3)
25fde0aa6cSHeikki Krogerus * @udc: Optional reference to the peripheral controller device
26fde0aa6cSHeikki Krogerus * @set: Callback for setting the role
27fde0aa6cSHeikki Krogerus * @get: Callback for getting the role (optional)
28fde0aa6cSHeikki Krogerus * @allow_userspace_control: If true userspace may change the role through sysfs
2969af044aSHeikki Krogerus * @driver_data: Private data pointer
30e5256194SHeikki Krogerus * @name: Name for the switch (optional)
31fde0aa6cSHeikki Krogerus *
32fde0aa6cSHeikki Krogerus * @usb2_port and @usb3_port will point to the USB host port and @udc to the USB
33fde0aa6cSHeikki Krogerus * device controller behind the USB connector with the role switch. If
34fde0aa6cSHeikki Krogerus * @usb2_port, @usb3_port and @udc are included in the description, the
35fde0aa6cSHeikki Krogerus * reference count for them should be incremented by the caller of
36fde0aa6cSHeikki Krogerus * usb_role_switch_register() before registering the switch.
37fde0aa6cSHeikki Krogerus */
38fde0aa6cSHeikki Krogerus struct usb_role_switch_desc {
39ec69e953SHeikki Krogerus struct fwnode_handle *fwnode;
40fde0aa6cSHeikki Krogerus struct device *usb2_port;
41fde0aa6cSHeikki Krogerus struct device *usb3_port;
42fde0aa6cSHeikki Krogerus struct device *udc;
43fde0aa6cSHeikki Krogerus usb_role_switch_set_t set;
44fde0aa6cSHeikki Krogerus usb_role_switch_get_t get;
45fde0aa6cSHeikki Krogerus bool allow_userspace_control;
4669af044aSHeikki Krogerus void *driver_data;
47e5256194SHeikki Krogerus const char *name;
48fde0aa6cSHeikki Krogerus };
49fde0aa6cSHeikki Krogerus
5097760765SYu Chen
5197760765SYu Chen #if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
52fde0aa6cSHeikki Krogerus int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role);
53fde0aa6cSHeikki Krogerus enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw);
54fde0aa6cSHeikki Krogerus struct usb_role_switch *usb_role_switch_get(struct device *dev);
55a31f0177SHeikki Krogerus struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *node);
56fde0aa6cSHeikki Krogerus void usb_role_switch_put(struct usb_role_switch *sw);
57fde0aa6cSHeikki Krogerus
58fde0aa6cSHeikki Krogerus struct usb_role_switch *
59c6919d5eSHeikki Krogerus usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode);
60c6919d5eSHeikki Krogerus
61c6919d5eSHeikki Krogerus struct usb_role_switch *
62fde0aa6cSHeikki Krogerus usb_role_switch_register(struct device *parent,
63fde0aa6cSHeikki Krogerus const struct usb_role_switch_desc *desc);
64fde0aa6cSHeikki Krogerus void usb_role_switch_unregister(struct usb_role_switch *sw);
6569af044aSHeikki Krogerus
6669af044aSHeikki Krogerus void usb_role_switch_set_drvdata(struct usb_role_switch *sw, void *data);
6769af044aSHeikki Krogerus void *usb_role_switch_get_drvdata(struct usb_role_switch *sw);
6873e33008SChunfeng Yun const char *usb_role_string(enum usb_role role);
6997760765SYu Chen #else
usb_role_switch_set_role(struct usb_role_switch * sw,enum usb_role role)7097760765SYu Chen static inline int usb_role_switch_set_role(struct usb_role_switch *sw,
7197760765SYu Chen enum usb_role role)
7297760765SYu Chen {
7397760765SYu Chen return 0;
7497760765SYu Chen }
7597760765SYu Chen
usb_role_switch_get_role(struct usb_role_switch * sw)7697760765SYu Chen static inline enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
7797760765SYu Chen {
7897760765SYu Chen return USB_ROLE_NONE;
7997760765SYu Chen }
8097760765SYu Chen
usb_role_switch_get(struct device * dev)8197760765SYu Chen static inline struct usb_role_switch *usb_role_switch_get(struct device *dev)
8297760765SYu Chen {
8397760765SYu Chen return ERR_PTR(-ENODEV);
8497760765SYu Chen }
8597760765SYu Chen
86a31f0177SHeikki Krogerus static inline struct usb_role_switch *
fwnode_usb_role_switch_get(struct fwnode_handle * node)87a31f0177SHeikki Krogerus fwnode_usb_role_switch_get(struct fwnode_handle *node)
88a31f0177SHeikki Krogerus {
89a31f0177SHeikki Krogerus return ERR_PTR(-ENODEV);
90a31f0177SHeikki Krogerus }
91a31f0177SHeikki Krogerus
usb_role_switch_put(struct usb_role_switch * sw)9297760765SYu Chen static inline void usb_role_switch_put(struct usb_role_switch *sw) { }
9397760765SYu Chen
9497760765SYu Chen static inline struct usb_role_switch *
usb_role_switch_find_by_fwnode(const struct fwnode_handle * fwnode)95*945c37edSLinyu Yuan usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
96*945c37edSLinyu Yuan {
97*945c37edSLinyu Yuan return NULL;
98*945c37edSLinyu Yuan }
99*945c37edSLinyu Yuan
100*945c37edSLinyu Yuan static inline struct usb_role_switch *
usb_role_switch_register(struct device * parent,const struct usb_role_switch_desc * desc)10197760765SYu Chen usb_role_switch_register(struct device *parent,
10297760765SYu Chen const struct usb_role_switch_desc *desc)
10397760765SYu Chen {
10497760765SYu Chen return ERR_PTR(-ENODEV);
10597760765SYu Chen }
10697760765SYu Chen
usb_role_switch_unregister(struct usb_role_switch * sw)10797760765SYu Chen static inline void usb_role_switch_unregister(struct usb_role_switch *sw) { }
10869af044aSHeikki Krogerus
10969af044aSHeikki Krogerus static inline void
usb_role_switch_set_drvdata(struct usb_role_switch * sw,void * data)11069af044aSHeikki Krogerus usb_role_switch_set_drvdata(struct usb_role_switch *sw, void *data)
11169af044aSHeikki Krogerus {
11269af044aSHeikki Krogerus }
11369af044aSHeikki Krogerus
usb_role_switch_get_drvdata(struct usb_role_switch * sw)11469af044aSHeikki Krogerus static inline void *usb_role_switch_get_drvdata(struct usb_role_switch *sw)
11569af044aSHeikki Krogerus {
11669af044aSHeikki Krogerus return NULL;
11769af044aSHeikki Krogerus }
11869af044aSHeikki Krogerus
usb_role_string(enum usb_role role)11973e33008SChunfeng Yun static inline const char *usb_role_string(enum usb_role role)
12073e33008SChunfeng Yun {
12173e33008SChunfeng Yun return "unknown";
12273e33008SChunfeng Yun }
12373e33008SChunfeng Yun
12497760765SYu Chen #endif
125fde0aa6cSHeikki Krogerus
126fde0aa6cSHeikki Krogerus #endif /* __LINUX_USB_ROLE_H */
127