Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 
0003 #ifndef __USB_TYPEC_ALTMODE_H
0004 #define __USB_TYPEC_ALTMODE_H
0005 
0006 #include <linux/mod_devicetable.h>
0007 #include <linux/usb/typec.h>
0008 #include <linux/device.h>
0009 
0010 #define MODE_DISCOVERY_MAX  6
0011 
0012 struct typec_altmode_ops;
0013 
0014 /**
0015  * struct typec_altmode - USB Type-C alternate mode device
0016  * @dev: Driver model's view of this device
0017  * @svid: Standard or Vendor ID (SVID) of the alternate mode
0018  * @mode: Index of the Mode
0019  * @vdo: VDO returned by Discover Modes USB PD command
0020  * @active: Tells has the mode been entered or not
0021  * @desc: Optional human readable description of the mode
0022  * @ops: Operations vector from the driver
0023  */
0024 struct typec_altmode {
0025     struct device           dev;
0026     u16             svid;
0027     int             mode;
0028     u32             vdo;
0029     unsigned int            active:1;
0030 
0031     char                *desc;
0032     const struct typec_altmode_ops  *ops;
0033 };
0034 
0035 #define to_typec_altmode(d) container_of(d, struct typec_altmode, dev)
0036 
0037 static inline void typec_altmode_set_drvdata(struct typec_altmode *altmode,
0038                          void *data)
0039 {
0040     dev_set_drvdata(&altmode->dev, data);
0041 }
0042 
0043 static inline void *typec_altmode_get_drvdata(struct typec_altmode *altmode)
0044 {
0045     return dev_get_drvdata(&altmode->dev);
0046 }
0047 
0048 /**
0049  * struct typec_altmode_ops - Alternate mode specific operations vector
0050  * @enter: Operations to be executed with Enter Mode Command
0051  * @exit: Operations to be executed with Exit Mode Command
0052  * @attention: Callback for Attention Command
0053  * @vdm: Callback for SVID specific commands
0054  * @notify: Communication channel for platform and the alternate mode
0055  * @activate: User callback for Enter/Exit Mode
0056  */
0057 struct typec_altmode_ops {
0058     int (*enter)(struct typec_altmode *altmode, u32 *vdo);
0059     int (*exit)(struct typec_altmode *altmode);
0060     void (*attention)(struct typec_altmode *altmode, u32 vdo);
0061     int (*vdm)(struct typec_altmode *altmode, const u32 hdr,
0062            const u32 *vdo, int cnt);
0063     int (*notify)(struct typec_altmode *altmode, unsigned long conf,
0064               void *data);
0065     int (*activate)(struct typec_altmode *altmode, int activate);
0066 };
0067 
0068 int typec_altmode_enter(struct typec_altmode *altmode, u32 *vdo);
0069 int typec_altmode_exit(struct typec_altmode *altmode);
0070 void typec_altmode_attention(struct typec_altmode *altmode, u32 vdo);
0071 int typec_altmode_vdm(struct typec_altmode *altmode,
0072               const u32 header, const u32 *vdo, int count);
0073 int typec_altmode_notify(struct typec_altmode *altmode, unsigned long conf,
0074              void *data);
0075 const struct typec_altmode *
0076 typec_altmode_get_partner(struct typec_altmode *altmode);
0077 
0078 /*
0079  * These are the connector states (USB, Safe and Alt Mode) defined in USB Type-C
0080  * Specification. SVID specific connector states are expected to follow and
0081  * start from the value TYPEC_STATE_MODAL.
0082  */
0083 enum {
0084     TYPEC_STATE_SAFE,   /* USB Safe State */
0085     TYPEC_STATE_USB,    /* USB Operation */
0086     TYPEC_STATE_MODAL,  /* Alternate Modes */
0087 };
0088 
0089 /*
0090  * For the muxes there is no difference between Accessory Modes and Alternate
0091  * Modes, so the Accessory Modes are supplied with specific modal state values
0092  * here. Unlike with Alternate Modes, where the mux will be linked with the
0093  * alternate mode device, the mux for Accessory Modes will be linked with the
0094  * port device instead.
0095  *
0096  * Port drivers can use TYPEC_MODE_AUDIO and TYPEC_MODE_DEBUG as the mode
0097  * value for typec_set_mode() when accessory modes are supported.
0098  *
0099  * USB4 also requires that the pins on the connector are repurposed, just like
0100  * Alternate Modes. USB4 mode is however not entered with the Enter Mode Command
0101  * like the Alternate Modes are, but instead with a special Enter_USB Message.
0102  * The Enter_USB Message can also be used for setting to connector to operate in
0103  * USB 3.2 or in USB 2.0 mode instead of USB4.
0104  *
0105  * The Enter_USB specific "USB Modes" are also supplied here as special modal
0106  * state values, just like the Accessory Modes.
0107  */
0108 enum {
0109     TYPEC_MODE_USB2 = TYPEC_STATE_MODAL,    /* USB 2.0 mode */
0110     TYPEC_MODE_USB3,            /* USB 3.2 mode */
0111     TYPEC_MODE_USB4,            /* USB4 mode */
0112     TYPEC_MODE_AUDIO,           /* Audio Accessory */
0113     TYPEC_MODE_DEBUG,           /* Debug Accessory */
0114 };
0115 
0116 #define TYPEC_MODAL_STATE(_state_)  ((_state_) + TYPEC_STATE_MODAL)
0117 
0118 struct typec_altmode *typec_altmode_get_plug(struct typec_altmode *altmode,
0119                          enum typec_plug_index index);
0120 void typec_altmode_put_plug(struct typec_altmode *plug);
0121 
0122 struct typec_altmode *typec_match_altmode(struct typec_altmode **altmodes,
0123                       size_t n, u16 svid, u8 mode);
0124 
0125 /**
0126  * typec_altmode_get_orientation - Get cable plug orientation
0127  * @altmode: Handle to the alternate mode
0128  */
0129 static inline enum typec_orientation
0130 typec_altmode_get_orientation(struct typec_altmode *altmode)
0131 {
0132     return typec_get_orientation(typec_altmode2port(altmode));
0133 }
0134 
0135 /**
0136  * typec_altmode_get_svdm_version - Get negotiated SVDM version
0137  * @altmode: Handle to the alternate mode
0138  */
0139 static inline int
0140 typec_altmode_get_svdm_version(struct typec_altmode *altmode)
0141 {
0142     return typec_get_negotiated_svdm_version(typec_altmode2port(altmode));
0143 }
0144 
0145 /**
0146  * struct typec_altmode_driver - USB Type-C alternate mode device driver
0147  * @id_table: Null terminated array of SVIDs
0148  * @probe: Callback for device binding
0149  * @remove: Callback for device unbinding
0150  * @driver: Device driver model driver
0151  *
0152  * These drivers will be bind to the partner alternate mode devices. They will
0153  * handle all SVID specific communication.
0154  */
0155 struct typec_altmode_driver {
0156     const struct typec_device_id *id_table;
0157     int (*probe)(struct typec_altmode *altmode);
0158     void (*remove)(struct typec_altmode *altmode);
0159     struct device_driver driver;
0160 };
0161 
0162 #define to_altmode_driver(d) container_of(d, struct typec_altmode_driver, \
0163                       driver)
0164 
0165 /**
0166  * typec_altmode_register_driver - registers a USB Type-C alternate mode
0167  *                 device driver
0168  * @drv: pointer to struct typec_altmode_driver
0169  *
0170  * These drivers will be bind to the partner alternate mode devices. They will
0171  * handle all SVID specific communication.
0172  */
0173 #define typec_altmode_register_driver(drv) \
0174         __typec_altmode_register_driver(drv, THIS_MODULE)
0175 int __typec_altmode_register_driver(struct typec_altmode_driver *drv,
0176                     struct module *module);
0177 /**
0178  * typec_altmode_unregister_driver - unregisters a USB Type-C alternate mode
0179  *                   device driver
0180  * @drv: pointer to struct typec_altmode_driver
0181  *
0182  * These drivers will be bind to the partner alternate mode devices. They will
0183  * handle all SVID specific communication.
0184  */
0185 void typec_altmode_unregister_driver(struct typec_altmode_driver *drv);
0186 
0187 #define module_typec_altmode_driver(__typec_altmode_driver) \
0188     module_driver(__typec_altmode_driver, typec_altmode_register_driver, \
0189               typec_altmode_unregister_driver)
0190 
0191 #endif /* __USB_TYPEC_ALTMODE_H */