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 <[email protected]>

Reviewed-by: Guenter Roeck <[email protected]>

> ---
> 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
> 

Reply via email to