On Fri, Feb 05, 2021 at 11:34:09AM +0800, Kyle Tso wrote: > PD Spec Revision 3.0 Version 2.0 + ECNs 2020-12-10 > 6.4.4.2.3 Structured VDM Version > "The Structured VDM Version field of the Discover Identity Command > sent and received during VDM discovery Shall be used to determine the > lowest common Structured VDM Version supported by the Port Partners or > Cable Plug and Shall continue to operate using this Specification > Revision until they are Detached." > > Add a variable in typec_capability to specify the highest SVDM version > supported by the port and another variable in typec_partner to cache the > negotiated SVDM version between the port and the partner. > > Also add setter/getter functions for the negotiated SVDM version. > > Signed-off-by: Kyle Tso <kyletso@xxxxxxxxxx> Reviewed-by: Guenter Roeck <linux@xxxxxxxxxxxx> > --- > Changes since v5 > - !! most changes are from Heikki > - location of the negotiated SVDM version is changed. Now the variable > resides in typec_partner > - The setter and getter functions were modified according to the above > changes > - the default SVDM version is stored upon calling to > typec_register_partner > > drivers/usb/typec/class.c | 43 +++++++++++++++++++++++++++++++ > include/linux/usb/typec.h | 12 +++++++++ > include/linux/usb/typec_altmode.h | 10 +++++++ > 3 files changed, 65 insertions(+) > > diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c > index b4a5d9d4564f..45f0bf65e9ab 100644 > --- a/drivers/usb/typec/class.c > +++ b/drivers/usb/typec/class.c > @@ -38,6 +38,7 @@ struct typec_partner { > struct ida mode_ids; > int num_altmodes; > u16 pd_revision; /* 0300H = "3.0" */ > + enum usb_pd_svdm_ver svdm_version; > }; > > struct typec_port { > @@ -824,6 +825,20 @@ typec_partner_register_altmode(struct typec_partner *partner, > } > EXPORT_SYMBOL_GPL(typec_partner_register_altmode); > > +/** > + * typec_partner_set_svdm_version - Set negotiated Structured VDM (SVDM) Version > + * @partner: USB Type-C Partner that supports SVDM > + * @svdm_version: Negotiated SVDM Version > + * > + * This routine is used to save the negotiated SVDM Version. > + */ > +void typec_partner_set_svdm_version(struct typec_partner *partner, > + enum usb_pd_svdm_ver svdm_version) > +{ > + partner->svdm_version = svdm_version; > +} > +EXPORT_SYMBOL_GPL(typec_partner_set_svdm_version); > + > /** > * typec_register_partner - Register a USB Type-C Partner > * @port: The USB Type-C Port the partner is connected to > @@ -848,6 +863,7 @@ struct typec_partner *typec_register_partner(struct typec_port *port, > partner->accessory = desc->accessory; > partner->num_altmodes = -1; > partner->pd_revision = desc->pd_revision; > + partner->svdm_version = port->cap->svdm_version; > > if (desc->identity) { > /* > @@ -1894,6 +1910,33 @@ EXPORT_SYMBOL_GPL(typec_set_mode); > > /* --------------------------------------- */ > > +/** > + * typec_get_negotiated_svdm_version - Get negotiated SVDM Version > + * @port: USB Type-C Port. > + * > + * Get the negotiated SVDM Version. The Version is set to the port default > + * value stored in typec_capability on partner registration, and updated after > + * a successful Discover Identity if the negotiated value is less than the > + * default value. > + * > + * Returns usb_pd_svdm_ver if the partner has been registered otherwise -ENODEV. > + */ > +int typec_get_negotiated_svdm_version(struct typec_port *port) > +{ > + enum usb_pd_svdm_ver svdm_version; > + struct device *partner_dev; > + > + partner_dev = device_find_child(&port->dev, NULL, partner_match); > + if (!partner_dev) > + return -ENODEV; > + > + svdm_version = to_typec_partner(partner_dev)->svdm_version; > + put_device(partner_dev); > + > + return svdm_version; > +} > +EXPORT_SYMBOL_GPL(typec_get_negotiated_svdm_version); > + > /** > * typec_get_drvdata - Return private driver data pointer > * @port: USB Type-C port > diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h > index a94df82ab62f..91b4303ca305 100644 > --- a/include/linux/usb/typec.h > +++ b/include/linux/usb/typec.h > @@ -217,12 +217,19 @@ struct typec_operations { > enum typec_port_type type); > }; > > +enum usb_pd_svdm_ver { > + SVDM_VER_1_0 = 0, > + SVDM_VER_2_0 = 1, > + SVDM_VER_MAX = SVDM_VER_2_0, > +}; > + > /* > * struct typec_capability - USB Type-C Port Capabilities > * @type: Supported power role of the port > * @data: Supported data role of the port > * @revision: USB Type-C Specification release. Binary coded decimal > * @pd_revision: USB Power Delivery Specification revision if supported > + * @svdm_version: USB PD Structured VDM version if supported > * @prefer_role: Initial role preference (DRP ports). > * @accessory: Supported Accessory Modes > * @fwnode: Optional fwnode of the port > @@ -236,6 +243,7 @@ struct typec_capability { > enum typec_port_data data; > u16 revision; /* 0120H = "1.2" */ > u16 pd_revision; /* 0300H = "3.0" */ > + enum usb_pd_svdm_ver svdm_version; > int prefer_role; > enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; > unsigned int orientation_aware:1; > @@ -286,4 +294,8 @@ int typec_find_orientation(const char *name); > int typec_find_port_power_role(const char *name); > int typec_find_power_role(const char *name); > int typec_find_port_data_role(const char *name); > + > +void typec_partner_set_svdm_version(struct typec_partner *partner, > + enum usb_pd_svdm_ver svdm_version); > +int typec_get_negotiated_svdm_version(struct typec_port *port); > #endif /* __LINUX_USB_TYPEC_H */ > diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h > index 5e0a7b7647c3..65933cbe9129 100644 > --- a/include/linux/usb/typec_altmode.h > +++ b/include/linux/usb/typec_altmode.h > @@ -132,6 +132,16 @@ typec_altmode_get_orientation(struct typec_altmode *altmode) > return typec_get_orientation(typec_altmode2port(altmode)); > } > > +/** > + * typec_altmode_get_svdm_version - Get negotiated SVDM version > + * @altmode: Handle to the alternate mode > + */ > +static inline int > +typec_altmode_get_svdm_version(struct typec_altmode *altmode) > +{ > + return typec_get_negotiated_svdm_version(typec_altmode2port(altmode)); > +} > + > /** > * struct typec_altmode_driver - USB Type-C alternate mode device driver > * @id_table: Null terminated array of SVIDs > -- > 2.30.0.365.g02bc693789-goog >