2024-03-05 03:00:17

by Jameson Thies

[permalink] [raw]
Subject: [PATCH v4 0/4] usb: typec: ucsi: Expand SOP/SOP' Discovery

Hi Heikki,

This patch series expands support for partner and cable discover in the
UCSI driver. There are a few pieces here.

1. Some cleanup of the GET_CABLE_PROP definitions in ucsi.h.
2. Cable discovery and registration with the USB Type-C connector class.
3. Partner/Cable identity registration with the USB Type-C connector
class.
4. SOP' alternate mode registration with the USB-C connector class using
a cable plug.

These have been tested on a the usb-testing branch merged with a
chromeOS 6.8-rc2 kernel. Let me know if you have any questions.

Thanks,
Jameson

Changes in v4:
- Cleaned up redundent ucsi_send_command calls for discovering identity.

Changes in v3:
- Fixed CC stable and email threading issue.

Changes in v2:
- Re-ordered memset call and null assignment when unregistering partners
and cables.
- Supports registering partner and cable identity with UCSI versions
before v2.0.
- Shortened lines to within 80 characters with the exception of two
error log lines with three indentations.
- Tested on usb-testing branch merged with chromeOS 6.8-rc2 kernel.

Jameson Thies (4):
usb: typec: ucsi: Clean up UCSI_CABLE_PROP macros
usb: typec: ucsi: Register cables based on GET_CABLE_PROPERTY
usb: typec: ucsi: Register SOP/SOP' Discover Identity Responses
usb: typec: ucsi: Register SOP' alternate modes with cable plug

drivers/usb/typec/ucsi/ucsi.c | 245 ++++++++++++++++++++++++++++++++++
drivers/usb/typec/ucsi/ucsi.h | 40 +++++-
2 files changed, 283 insertions(+), 2 deletions(-)


base-commit: a14e6fd1b67799da7da9cc344023bd16aaf0d17d
--
2.44.0.rc1.240.g4c46232300-goog



2024-03-05 03:00:20

by Jameson Thies

[permalink] [raw]
Subject: [PATCH v4 4/4] usb: typec: ucsi: Register SOP' alternate modes with cable plug

Register SOP' alternate modes with a Type-C Connector Class cable plug.
Alternate modes are queried from the PPM using the GET_ALTERNATE_MODES
command with recipient set to SOP'.

Reviewed-by: Benson Leung <[email protected]>
Reviewed-by: Prashant Malani <[email protected]>
Reviewed-by: Heikki Krogerus <[email protected]>
Signed-off-by: Jameson Thies <[email protected]>
---
SOP' GET_ALTERNATE_MODE responses from the PPM are correctly registered
to the cable plug.
nospike-rev4 /sys/class/typec # ls port0-cable/port0-plug0/
device port0-plug0.0 port0-plug0.1 power subsystem uevent

Changes in v4:
- None.

Changes in v3:
- None.

Changes in v2:
- Shortened lines to within 80 characters.
- Tested on usb-testing branch merged with chromeOS 6.8-rc2 kernel.

drivers/usb/typec/ucsi/ucsi.c | 60 +++++++++++++++++++++++++++++++++++
drivers/usb/typec/ucsi/ucsi.h | 2 ++
2 files changed, 62 insertions(+)

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 3b64a0f51041c..cf52cb34d2859 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -399,6 +399,27 @@ static int ucsi_register_altmode(struct ucsi_connector *con,

con->partner_altmode[i] = alt;
break;
+ case UCSI_RECIPIENT_SOP_P:
+ i = ucsi_next_altmode(con->plug_altmode);
+ if (i < 0) {
+ ret = i;
+ goto err;
+ }
+
+ ret = ucsi_altmode_next_mode(con->plug_altmode, desc->svid);
+ if (ret < 0)
+ return ret;
+
+ desc->mode = ret;
+
+ alt = typec_plug_register_altmode(con->plug, desc);
+ if (IS_ERR(alt)) {
+ ret = PTR_ERR(alt);
+ goto err;
+ }
+
+ con->plug_altmode[i] = alt;
+ break;
default:
return -EINVAL;
}
@@ -566,6 +587,9 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
case UCSI_RECIPIENT_SOP:
adev = con->partner_altmode;
break;
+ case UCSI_RECIPIENT_SOP_P:
+ adev = con->plug_altmode;
+ break;
default:
return;
}
@@ -836,6 +860,33 @@ static void ucsi_unregister_partner_pdos(struct ucsi_connector *con)
con->partner_pd = NULL;
}

+static int ucsi_register_plug(struct ucsi_connector *con)
+{
+ struct typec_plug *plug;
+ struct typec_plug_desc desc = {.index = TYPEC_PLUG_SOP_P};
+
+ plug = typec_register_plug(con->cable, &desc);
+ if (IS_ERR(plug)) {
+ dev_err(con->ucsi->dev,
+ "con%d: failed to register plug (%ld)\n", con->num,
+ PTR_ERR(plug));
+ return PTR_ERR(plug);
+ }
+
+ con->plug = plug;
+ return 0;
+}
+
+static void ucsi_unregister_plug(struct ucsi_connector *con)
+{
+ if (!con->plug)
+ return;
+
+ ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP_P);
+ typec_unregister_plug(con->plug);
+ con->plug = NULL;
+}
+
static int ucsi_register_cable(struct ucsi_connector *con)
{
struct typec_cable *cable;
@@ -879,6 +930,7 @@ static void ucsi_unregister_cable(struct ucsi_connector *con)
if (!con->cable)
return;

+ ucsi_unregister_plug(con);
typec_unregister_cable(con->cable);
memset(&con->cable_identity, 0, sizeof(con->cable_identity));
con->cable = NULL;
@@ -1085,6 +1137,14 @@ static int ucsi_check_cable(struct ucsi_connector *con)
if (ret < 0)
return ret;

+ ret = ucsi_register_plug(con);
+ if (ret < 0)
+ return ret;
+
+ ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P);
+ if (ret < 0)
+ return ret;
+
return 0;
}

diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index b89fae82e8ce7..32daf5f586505 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -429,9 +429,11 @@ struct ucsi_connector {
struct typec_port *port;
struct typec_partner *partner;
struct typec_cable *cable;
+ struct typec_plug *plug;

struct typec_altmode *port_altmode[UCSI_MAX_ALTMODES];
struct typec_altmode *partner_altmode[UCSI_MAX_ALTMODES];
+ struct typec_altmode *plug_altmode[UCSI_MAX_ALTMODES];

struct typec_capability typec_cap;

--
2.44.0.rc1.240.g4c46232300-goog


2024-03-05 03:00:26

by Jameson Thies

[permalink] [raw]
Subject: [PATCH v4 1/4] usb: typec: ucsi: Clean up UCSI_CABLE_PROP macros

Clean up UCSI_CABLE_PROP macros by fixing a bitmask shifting error for
plug type and updating the modal support macro for consistent naming.

Fixes: 3cf657f07918 ("usb: typec: ucsi: Remove all bit-fields")
Cc: [email protected]
Reviewed-by: Benson Leung <[email protected]>
Reviewed-by: Prashant Malani <[email protected]>
Reviewed-by: Dmitry Baryshkov <[email protected]>
Signed-off-by: Jameson Thies <[email protected]>
---
Changes in v4:
- None.

Changes in v3:
- Fixed CC stable.

Changes in v2:
- Tested on usb-testing branch merged with chromeOS 6.8-rc2 kernel.

drivers/usb/typec/ucsi/ucsi.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 7e35ffbe0a6f2..469a2baf472e4 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -259,12 +259,12 @@ struct ucsi_cable_property {
#define UCSI_CABLE_PROP_FLAG_VBUS_IN_CABLE BIT(0)
#define UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE BIT(1)
#define UCSI_CABLE_PROP_FLAG_DIRECTIONALITY BIT(2)
-#define UCSI_CABLE_PROP_FLAG_PLUG_TYPE(_f_) ((_f_) & GENMASK(3, 0))
+#define UCSI_CABLE_PROP_FLAG_PLUG_TYPE(_f_) (((_f_) & GENMASK(4, 3)) >> 3)
#define UCSI_CABLE_PROPERTY_PLUG_TYPE_A 0
#define UCSI_CABLE_PROPERTY_PLUG_TYPE_B 1
#define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2
#define UCSI_CABLE_PROPERTY_PLUG_OTHER 3
-#define UCSI_CABLE_PROP_MODE_SUPPORT BIT(5)
+#define UCSI_CABLE_PROP_FLAG_MODE_SUPPORT BIT(5)
u8 latency;
} __packed;

--
2.44.0.rc1.240.g4c46232300-goog


2024-03-05 03:01:00

by Jameson Thies

[permalink] [raw]
Subject: [PATCH v4 2/4] usb: typec: ucsi: Register cables based on GET_CABLE_PROPERTY

Register cables with the Type-C Connector Class in the UCSI driver based
on the PPM response to GET_CABLE_PROPERTY. Registered cable properties
include plug type, cable type and major revision.

Reviewed-by: Benson Leung <[email protected]>
Reviewed-by: Prashant Malani <[email protected]>
Reviewed-by: Dmitry Baryshkov <[email protected]>
Reviewed-by: Heikki Krogerus <[email protected]>
Signed-off-by: Jameson Thies <[email protected]>
---
Expected cable properties populate the USB Type-C connector class sysfs
paths:
nospike-rev4 /sys/class/typec # ls port0-cable
device identity plug_type port0-plug0 power subsystem type uevent
usb_power_delivery_revision

Changes in v4:
- None.

Changes in v3:
- None.

Changes in v2:
- Shortened lines to within 80 characters.
- Tested on usb-testing branch merged with chromeOS 6.8-rc2 kernel.

drivers/usb/typec/ucsi/ucsi.c | 73 +++++++++++++++++++++++++++++++++++
drivers/usb/typec/ucsi/ucsi.h | 5 +++
2 files changed, 78 insertions(+)

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index ae105383e69e7..7c84687b5d1a3 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -734,6 +734,52 @@ static void ucsi_unregister_partner_pdos(struct ucsi_connector *con)
con->partner_pd = NULL;
}

+static int ucsi_register_cable(struct ucsi_connector *con)
+{
+ struct typec_cable *cable;
+ struct typec_cable_desc desc = {};
+
+ switch (UCSI_CABLE_PROP_FLAG_PLUG_TYPE(con->cable_prop.flags)) {
+ case UCSI_CABLE_PROPERTY_PLUG_TYPE_A:
+ desc.type = USB_PLUG_TYPE_A;
+ break;
+ case UCSI_CABLE_PROPERTY_PLUG_TYPE_B:
+ desc.type = USB_PLUG_TYPE_B;
+ break;
+ case UCSI_CABLE_PROPERTY_PLUG_TYPE_C:
+ desc.type = USB_PLUG_TYPE_C;
+ break;
+ default:
+ desc.type = USB_PLUG_NONE;
+ break;
+ }
+
+ desc.active = !!(UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE &
+ con->cable_prop.flags);
+ desc.pd_revision = UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV_AS_BCD(
+ con->cable_prop.flags);
+
+ cable = typec_register_cable(con->port, &desc);
+ if (IS_ERR(cable)) {
+ dev_err(con->ucsi->dev,
+ "con%d: failed to register cable (%ld)\n", con->num,
+ PTR_ERR(cable));
+ return PTR_ERR(cable);
+ }
+
+ con->cable = cable;
+ return 0;
+}
+
+static void ucsi_unregister_cable(struct ucsi_connector *con)
+{
+ if (!con->cable)
+ return;
+
+ typec_unregister_cable(con->cable);
+ con->cable = NULL;
+}
+
static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
{
switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
@@ -807,6 +853,7 @@ static void ucsi_unregister_partner(struct ucsi_connector *con)
typec_partner_set_usb_power_delivery(con->partner, NULL);
ucsi_unregister_partner_pdos(con);
ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP);
+ ucsi_unregister_cable(con);
typec_unregister_partner(con->partner);
con->partner = NULL;
}
@@ -907,6 +954,30 @@ static int ucsi_check_connection(struct ucsi_connector *con)
return 0;
}

+static int ucsi_check_cable(struct ucsi_connector *con)
+{
+ u64 command;
+ int ret;
+
+ if (con->cable)
+ return 0;
+
+ command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num);
+ ret = ucsi_send_command(con->ucsi, command, &con->cable_prop,
+ sizeof(con->cable_prop));
+ if (ret < 0) {
+ dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ ret = ucsi_register_cable(con);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static void ucsi_handle_connector_change(struct work_struct *work)
{
struct ucsi_connector *con = container_of(work, struct ucsi_connector,
@@ -948,6 +1019,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
ucsi_register_partner(con);
ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
+ ucsi_partner_task(con, ucsi_check_cable, 1, HZ);

if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
UCSI_CONSTAT_PWR_OPMODE_PD)
@@ -1346,6 +1418,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
ucsi_register_partner(con);
ucsi_pwr_opmode_change(con);
ucsi_port_psy_changed(con);
+ ucsi_check_cable(con);
}

/* Only notify USB controller if partner supports USB data */
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 469a2baf472e4..f0aabef0b7c64 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -265,6 +265,9 @@ struct ucsi_cable_property {
#define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2
#define UCSI_CABLE_PROPERTY_PLUG_OTHER 3
#define UCSI_CABLE_PROP_FLAG_MODE_SUPPORT BIT(5)
+#define UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV(_f_) (((_f_) & GENMASK(7, 6)) >> 6)
+#define UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV_AS_BCD(_f_) \
+ UCSI_SPEC_REVISION_TO_BCD(UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV(_f_))
u8 latency;
} __packed;

@@ -400,6 +403,7 @@ struct ucsi_connector {

struct typec_port *port;
struct typec_partner *partner;
+ struct typec_cable *cable;

struct typec_altmode *port_altmode[UCSI_MAX_ALTMODES];
struct typec_altmode *partner_altmode[UCSI_MAX_ALTMODES];
@@ -408,6 +412,7 @@ struct ucsi_connector {

struct ucsi_connector_status status;
struct ucsi_connector_capability cap;
+ struct ucsi_cable_property cable_prop;
struct power_supply *psy;
struct power_supply_desc psy_desc;
u32 rdo;
--
2.44.0.rc1.240.g4c46232300-goog


2024-03-11 17:28:57

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH v4 2/4] usb: typec: ucsi: Register cables based on GET_CABLE_PROPERTY

Hi,

On 05/03/2024 03:58, Jameson Thies wrote:
> Register cables with the Type-C Connector Class in the UCSI driver based
> on the PPM response to GET_CABLE_PROPERTY. Registered cable properties
> include plug type, cable type and major revision.
>
> Reviewed-by: Benson Leung <[email protected]>
> Reviewed-by: Prashant Malani <[email protected]>
> Reviewed-by: Dmitry Baryshkov <[email protected]>
> Reviewed-by: Heikki Krogerus <[email protected]>
> Signed-off-by: Jameson Thies <[email protected]>
> ---
> Expected cable properties populate the USB Type-C connector class sysfs
> paths:
> nospike-rev4 /sys/class/typec # ls port0-cable
> device identity plug_type port0-plug0 power subsystem type uevent
> usb_power_delivery_revision
>
> Changes in v4:
> - None.
>
> Changes in v3:
> - None.
>
> Changes in v2:
> - Shortened lines to within 80 characters.
> - Tested on usb-testing branch merged with chromeOS 6.8-rc2 kernel.
>
> drivers/usb/typec/ucsi/ucsi.c | 73 +++++++++++++++++++++++++++++++++++
> drivers/usb/typec/ucsi/ucsi.h | 5 +++
> 2 files changed, 78 insertions(+)

Since those were merged, I see the following errors on SM8550-QRD and SM8650-QRD running linux-next:

[ 8.668966] ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: UCSI_GET_PD_MESSAGE failed (-95)
[ 11.170560] ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: GET_CABLE_PROPERTY failed (-95)
[ 16.361678] ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: timeout waiting for UCSI sync write response
[ 21.409633] ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: error -ETIMEDOUT: PPM init failed

perhaps you should check the GET_CAPABILITY.bmOptionalFeatures bit 5 (Cable details supported) and 8 (GET_PD_MESSAGE supported)
before sending UCSI_GET_PD_MESSAGE and GET_CABLE_PROPERTY messages ?

With:
=================><====================================
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index cf52cb34d285..eec64a4c8cdd 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1189,8 +1189,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
ucsi_register_partner(con);
ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
- ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ);
- ucsi_partner_task(con, ucsi_check_cable, 1, HZ);
+ if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
+ ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ);
+ if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
+ ucsi_partner_task(con, ucsi_check_cable, 1, HZ);

if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
UCSI_CONSTAT_PWR_OPMODE_PD)
@@ -1589,8 +1591,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
ucsi_register_partner(con);
ucsi_pwr_opmode_change(con);
ucsi_port_psy_changed(con);
- ucsi_get_partner_identity(con);
- ucsi_check_cable(con);
+ if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
+ ucsi_get_partner_identity(con);
+ if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
+ ucsi_check_cable(con);
}

/* Only notify USB controller if partner supports USB data */
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 32daf5f58650..2e9c35a3af27 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -215,6 +215,7 @@ struct ucsi_capability {
#define UCSI_CAP_CABLE_DETAILS BIT(5)
#define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6)
#define UCSI_CAP_PD_RESET BIT(7)
+#define UCSI_CAP_GET_PD_MESSAGE BIT(8)
u16 reserved_1;
u8 num_alt_modes;
u8 reserved_2;
=================><====================================
it works fine again.

#regzbot introduced: 38ca416597b0

Thanks,
Neil

>
> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> index ae105383e69e7..7c84687b5d1a3 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -734,6 +734,52 @@ static void ucsi_unregister_partner_pdos(struct ucsi_connector *con)
> con->partner_pd = NULL;
> }
>
> +static int ucsi_register_cable(struct ucsi_connector *con)
> +{
> + struct typec_cable *cable;
> + struct typec_cable_desc desc = {};
> +
> + switch (UCSI_CABLE_PROP_FLAG_PLUG_TYPE(con->cable_prop.flags)) {
> + case UCSI_CABLE_PROPERTY_PLUG_TYPE_A:
> + desc.type = USB_PLUG_TYPE_A;
> + break;
> + case UCSI_CABLE_PROPERTY_PLUG_TYPE_B:
> + desc.type = USB_PLUG_TYPE_B;
> + break;
> + case UCSI_CABLE_PROPERTY_PLUG_TYPE_C:
> + desc.type = USB_PLUG_TYPE_C;
> + break;
> + default:
> + desc.type = USB_PLUG_NONE;
> + break;
> + }
> +
> + desc.active = !!(UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE &
> + con->cable_prop.flags);
> + desc.pd_revision = UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV_AS_BCD(
> + con->cable_prop.flags);
> +
> + cable = typec_register_cable(con->port, &desc);
> + if (IS_ERR(cable)) {
> + dev_err(con->ucsi->dev,
> + "con%d: failed to register cable (%ld)\n", con->num,
> + PTR_ERR(cable));
> + return PTR_ERR(cable);
> + }
> +
> + con->cable = cable;
> + return 0;
> +}
> +
> +static void ucsi_unregister_cable(struct ucsi_connector *con)
> +{
> + if (!con->cable)
> + return;
> +
> + typec_unregister_cable(con->cable);
> + con->cable = NULL;
> +}
> +
> static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
> {
> switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
> @@ -807,6 +853,7 @@ static void ucsi_unregister_partner(struct ucsi_connector *con)
> typec_partner_set_usb_power_delivery(con->partner, NULL);
> ucsi_unregister_partner_pdos(con);
> ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP);
> + ucsi_unregister_cable(con);
> typec_unregister_partner(con->partner);
> con->partner = NULL;
> }
> @@ -907,6 +954,30 @@ static int ucsi_check_connection(struct ucsi_connector *con)
> return 0;
> }
>
> +static int ucsi_check_cable(struct ucsi_connector *con)
> +{
> + u64 command;
> + int ret;
> +
> + if (con->cable)
> + return 0;
> +
> + command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num);
> + ret = ucsi_send_command(con->ucsi, command, &con->cable_prop,
> + sizeof(con->cable_prop));
> + if (ret < 0) {
> + dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n",
> + ret);
> + return ret;
> + }
> +
> + ret = ucsi_register_cable(con);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> static void ucsi_handle_connector_change(struct work_struct *work)
> {
> struct ucsi_connector *con = container_of(work, struct ucsi_connector,
> @@ -948,6 +1019,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
> ucsi_register_partner(con);
> ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
> ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
> + ucsi_partner_task(con, ucsi_check_cable, 1, HZ);
>
> if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
> UCSI_CONSTAT_PWR_OPMODE_PD)
> @@ -1346,6 +1418,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
> ucsi_register_partner(con);
> ucsi_pwr_opmode_change(con);
> ucsi_port_psy_changed(con);
> + ucsi_check_cable(con);
> }
>
> /* Only notify USB controller if partner supports USB data */
> diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
> index 469a2baf472e4..f0aabef0b7c64 100644
> --- a/drivers/usb/typec/ucsi/ucsi.h
> +++ b/drivers/usb/typec/ucsi/ucsi.h
> @@ -265,6 +265,9 @@ struct ucsi_cable_property {
> #define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2
> #define UCSI_CABLE_PROPERTY_PLUG_OTHER 3
> #define UCSI_CABLE_PROP_FLAG_MODE_SUPPORT BIT(5)
> +#define UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV(_f_) (((_f_) & GENMASK(7, 6)) >> 6)
> +#define UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV_AS_BCD(_f_) \
> + UCSI_SPEC_REVISION_TO_BCD(UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV(_f_))
> u8 latency;
> } __packed;
>
> @@ -400,6 +403,7 @@ struct ucsi_connector {
>
> struct typec_port *port;
> struct typec_partner *partner;
> + struct typec_cable *cable;
>
> struct typec_altmode *port_altmode[UCSI_MAX_ALTMODES];
> struct typec_altmode *partner_altmode[UCSI_MAX_ALTMODES];
> @@ -408,6 +412,7 @@ struct ucsi_connector {
>
> struct ucsi_connector_status status;
> struct ucsi_connector_capability cap;
> + struct ucsi_cable_property cable_prop;
> struct power_supply *psy;
> struct power_supply_desc psy_desc;
> u32 rdo;


2024-03-11 23:48:07

by Jameson Thies

[permalink] [raw]
Subject: Re: [PATCH v4 2/4] usb: typec: ucsi: Register cables based on GET_CABLE_PROPERTY

Hi Neil,
thanks for catching this. You're right, the UCSI driver doesn't need
to be sending these commands when they are not supported. I'll post a
followup patch properly gating ucsi_get_partner_identity and
ucsi_check_cable.

Thanks,
Jameson

2024-03-26 22:19:42

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v4 2/4] usb: typec: ucsi: Register cables based on GET_CABLE_PROPERTY

On Mon, Mar 11, 2024 at 06:28:41PM +0100, [email protected] wrote:
> On 05/03/2024 03:58, Jameson Thies wrote:
[..]
> With:
> =================><====================================
> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> index cf52cb34d285..eec64a4c8cdd 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -1189,8 +1189,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
> ucsi_register_partner(con);
> ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
> ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
> - ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ);
> - ucsi_partner_task(con, ucsi_check_cable, 1, HZ);
> + if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
> + ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ);
> + if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
> + ucsi_partner_task(con, ucsi_check_cable, 1, HZ);
>
> if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
> UCSI_CONSTAT_PWR_OPMODE_PD)
> @@ -1589,8 +1591,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
> ucsi_register_partner(con);
> ucsi_pwr_opmode_change(con);
> ucsi_port_psy_changed(con);
> - ucsi_get_partner_identity(con);
> - ucsi_check_cable(con);
> + if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
> + ucsi_get_partner_identity(con);
> + if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
> + ucsi_check_cable(con);
> }
>
> /* Only notify USB controller if partner supports USB data */
> diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
> index 32daf5f58650..2e9c35a3af27 100644
> --- a/drivers/usb/typec/ucsi/ucsi.h
> +++ b/drivers/usb/typec/ucsi/ucsi.h
> @@ -215,6 +215,7 @@ struct ucsi_capability {
> #define UCSI_CAP_CABLE_DETAILS BIT(5)
> #define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6)
> #define UCSI_CAP_PD_RESET BIT(7)
> +#define UCSI_CAP_GET_PD_MESSAGE BIT(8)
> u16 reserved_1;
> u8 num_alt_modes;
> u8 reserved_2;
> =================><====================================
> it works fine again.
>

The series broke role switching on qcs6490-rb3gen2 (next-20240326 is
broken). You're proposed addition brings it back, thank you.

Was this posted somewhere?

Regards,
Bjorn

2024-03-27 16:04:17

by Heikki Krogerus

[permalink] [raw]
Subject: Re: [PATCH v4 1/4] usb: typec: ucsi: Clean up UCSI_CABLE_PROP macros

On Tue, Mar 05, 2024 at 02:58:01AM +0000, Jameson Thies wrote:
> Clean up UCSI_CABLE_PROP macros by fixing a bitmask shifting error for
> plug type and updating the modal support macro for consistent naming.
>
> Fixes: 3cf657f07918 ("usb: typec: ucsi: Remove all bit-fields")
> Cc: [email protected]
> Reviewed-by: Benson Leung <[email protected]>
> Reviewed-by: Prashant Malani <[email protected]>
> Reviewed-by: Dmitry Baryshkov <[email protected]>
> Signed-off-by: Jameson Thies <[email protected]>

Reviewed-by: Heikki Krogerus <[email protected]>

> ---
> Changes in v4:
> - None.
>
> Changes in v3:
> - Fixed CC stable.
>
> Changes in v2:
> - Tested on usb-testing branch merged with chromeOS 6.8-rc2 kernel.
>
> drivers/usb/typec/ucsi/ucsi.h | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
> index 7e35ffbe0a6f2..469a2baf472e4 100644
> --- a/drivers/usb/typec/ucsi/ucsi.h
> +++ b/drivers/usb/typec/ucsi/ucsi.h
> @@ -259,12 +259,12 @@ struct ucsi_cable_property {
> #define UCSI_CABLE_PROP_FLAG_VBUS_IN_CABLE BIT(0)
> #define UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE BIT(1)
> #define UCSI_CABLE_PROP_FLAG_DIRECTIONALITY BIT(2)
> -#define UCSI_CABLE_PROP_FLAG_PLUG_TYPE(_f_) ((_f_) & GENMASK(3, 0))
> +#define UCSI_CABLE_PROP_FLAG_PLUG_TYPE(_f_) (((_f_) & GENMASK(4, 3)) >> 3)
> #define UCSI_CABLE_PROPERTY_PLUG_TYPE_A 0
> #define UCSI_CABLE_PROPERTY_PLUG_TYPE_B 1
> #define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2
> #define UCSI_CABLE_PROPERTY_PLUG_OTHER 3
> -#define UCSI_CABLE_PROP_MODE_SUPPORT BIT(5)
> +#define UCSI_CABLE_PROP_FLAG_MODE_SUPPORT BIT(5)
> u8 latency;
> } __packed;
>
> --
> 2.44.0.rc1.240.g4c46232300-goog

--
heikki