Re: [PATCHi v6 1/7] usb: typec: Manage SVDM version

From: Guenter Roeck
Date: Thu Feb 11 2021 - 23:10:38 EST


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
>