Skip to contentSkip to conversation

usb: typec: ucsi: Add support for SET_PDOS command

PATCH Superseded Pooja Katiyar 4 participants 7 messages Jun 6, 2025 – Jun 11, 2025

Subsystems (2)

v1 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

cover usb: typec: ucsi: Add support for SET_PDOS command

This series implements support for UCSI SET_PDOS command. It provides interface to send message out data structure and update source or sink capabilities PDOs on a connector over debugfs interface.

Pooja Katiyar (3):
usb: typec: ucsi: Add support for message out data structure
usb: typec: ucsi: Enable debugfs for message_out data structure
usb: typec: ucsi: Add support for SET_PDOS command

 drivers/usb/typec/ucsi/debugfs.c   | 32 ++++++++++++++++++++++++++++++
 drivers/usb/typec/ucsi/ucsi.h      | 17 ++++++++++++++++
 drivers/usb/typec/ucsi/ucsi_acpi.c | 16 +++++++++++++++
 3 files changed, 65 insertions(+)
Signature · 1 line
2.34.1
#1 lore raw

PATCH 1/3 usb: typec: ucsi: Add support for message out data structure

Add support for updating message out data structure for UCSI ACPI interface for UCSI 2.1 and UCSI 3.0 commands such as Set PDOs and LPM Firmware Update.

Additionally, introduce a wrapper function to access this operation via debugfs.

---
 drivers/usb/typec/ucsi/ucsi.h      | 10 ++++++++++
 drivers/usb/typec/ucsi/ucsi_acpi.c | 16 ++++++++++++++++
 2 files changed, 26 insertions(+)
drivers/usb/typec/ucsi/ucsi.h +10 -0
index 9c5278a0c5d4..14e3e362c54d 100644
@@ -79,6 +79,7 @@ struct ucsi_operations {
 	int (*read_cci)(struct ucsi *ucsi, u32 *cci);
 	int (*poll_cci)(struct ucsi *ucsi, u32 *cci);
 	int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len);
+	int (*write_message_out)(struct ucsi *ucsi, void *data, size_t data_len);
 	int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci,
 			    void *data, size_t size);
 	int (*async_control)(struct ucsi *ucsi, u64 command);
@@ -532,6 +533,15 @@ struct ucsi_connector {
 int ucsi_send_command(struct ucsi *ucsi, u64 command,
 		      void *retval, size_t size);
 
+static inline int ucsi_send_message_out(struct ucsi *ucsi,
+					void *data, size_t size)
+{
+	if (!ucsi->ops->write_message_out)
+		return -EOPNOTSUPP;
+
+	return ucsi->ops->write_message_out(ucsi, data, size);
+}
+
 void ucsi_altmode_update_active(struct ucsi_connector *con);
 int ucsi_resume(struct ucsi *ucsi);
 
drivers/usb/typec/ucsi/ucsi_acpi.c +16 -0
index 6b92f296e985..01d85e079d08 100644
@@ -86,6 +86,21 @@ static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_le
 	return 0;
 }
 
+static int ucsi_acpi_write_message_out(struct ucsi *ucsi, void *data, size_t data_len)
+{
+	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
+
+	if (!data || !data_len)
+		return -EINVAL;
+
+	if (ucsi->version <= UCSI_VERSION_1_2)
+		memcpy(ua->base + UCSI_MESSAGE_OUT, data, data_len);
+	else
+		memcpy(ua->base + UCSIv2_MESSAGE_OUT, data, data_len);
+
+	return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE);
+}
+
 static int ucsi_acpi_async_control(struct ucsi *ucsi, u64 command)
 {
 	struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
@@ -101,6 +116,7 @@ static const struct ucsi_operations ucsi_acpi_ops = {
 	.read_cci = ucsi_acpi_read_cci,
 	.poll_cci = ucsi_acpi_poll_cci,
 	.read_message_in = ucsi_acpi_read_message_in,
+	.write_message_out = ucsi_acpi_write_message_out,
 	.sync_control = ucsi_sync_control_common,
 	.async_control = ucsi_acpi_async_control
 };
Signature · 1 line
2.34.1
#2 lore raw

PATCH 2/3 usb: typec: ucsi: Enable debugfs for message_out data structure

In reply to Pooja Katiyar

Add debugfs entry for writing message_out data structure to handle UCSI 2.1 and 3.0 commands through debugfs interface.

Users writing to the message_out debugfs file should ensure the input data adheres to the following format:
1. Input must be a non-empty valid hexadecimal string.
2. Input length of hexadecimal string must not exceed 256 bytes of length to be in alignment with the message out data structure size as per the UCSI specification v2.1.
3. If the input string length is odd, then user needs to prepend a '0' to the first character for proper hex conversion.

Below are examples of valid hex strings. Note that these values are just examples. The exact values depend on specific command use case.

	#echo 1A2B3C4D > message_out
	#echo 01234567 > message_out
---
 drivers/usb/typec/ucsi/debugfs.c | 26 ++++++++++++++++++++++++++
 drivers/usb/typec/ucsi/ucsi.h    |  3 +++
 2 files changed, 29 insertions(+)
drivers/usb/typec/ucsi/debugfs.c +26 -0
index eae2b18a2d8a..004587ce3427 100644
@@ -76,6 +76,30 @@ static int ucsi_resp_show(struct seq_file *s, void *not_used)
 }
 DEFINE_SHOW_ATTRIBUTE(ucsi_resp);
 
+static ssize_t ucsi_message_out_write(struct file *file,
+				      const char __user *data, size_t count, loff_t *ppos)
+{
+	struct ucsi *ucsi = file->private_data;
+	int ret;
+
+	char *buf __free(kfree) = memdup_user_nul(data, count);
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
+
+	ret = hex2bin(ucsi->debugfs->message_out, buf,
+		      min(count / 2, sizeof(ucsi->debugfs->message_out)));
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static const struct file_operations ucsi_message_out_fops = {
+	.open = simple_open,
+	.write = ucsi_message_out_write,
+	.llseek = generic_file_llseek,
+};
+
 void ucsi_debugfs_register(struct ucsi *ucsi)
 {
 	ucsi->debugfs = kzalloc(sizeof(*ucsi->debugfs), GFP_KERNEL);
@@ -85,6 +109,8 @@ void ucsi_debugfs_register(struct ucsi *ucsi)
 	ucsi->debugfs->dentry = debugfs_create_dir(dev_name(ucsi->dev), ucsi_debugfs_root);
 	debugfs_create_file("command", 0200, ucsi->debugfs->dentry, ucsi, &ucsi_cmd_fops);
 	debugfs_create_file("response", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_resp_fops);
+	debugfs_create_file("message_out", 0200, ucsi->debugfs->dentry, ucsi,
+			    &ucsi_message_out_fops);
 }
 
 void ucsi_debugfs_unregister(struct ucsi *ucsi)
drivers/usb/typec/ucsi/ucsi.h +3 -0
index 14e3e362c54d..e7453b055ff7 100644
@@ -429,6 +429,8 @@ struct ucsi_bitfield {
 
 /* -------------------------------------------------------------------------- */
 
+#define MESSAGE_OUT_MAX_LEN 256
+
 struct ucsi_debugfs_entry {
 	u64 command;
 	struct ucsi_data {
@@ -436,6 +438,7 @@ struct ucsi_debugfs_entry {
 		u64 high;
 	} response;
 	u32 status;
+	u8 message_out[MESSAGE_OUT_MAX_LEN];
 	struct dentry *dentry;
 };
 
Signature · 1 line
2.34.1
Reviewed-by on v1 2/3
#3 lore raw

Re: [PATCH 2/3] usb: typec: ucsi: Enable debugfs for message_out data structure

Quoted 12 lines · Pooja Katiyar

Add debugfs entry for writing message_out data structure to handle UCSI 2.1 and 3.0 commands through debugfs interface.

Users writing to the message_out debugfs file should ensure the input data adheres to the following format:
1. Input must be a non-empty valid hexadecimal string.
2. Input length of hexadecimal string must not exceed 256 bytes of length to be in alignment with the message out data structure size as per the UCSI specification v2.1.
3. If the input string length is odd, then user needs to prepend a '0' to the first character for proper hex conversion.

Quoted 5 lines

Below are examples of valid hex strings. Note that these values are just examples. The exact values depend on specific command use case.

	#echo 1A2B3C4D > message_out
	#echo 01234567 > message_out
Signature · 2 lines
With Best Regards,
Andy Shevchenko
#4 lore raw

PATCH 3/3 usb: typec: ucsi: Add support for SET_PDOS command

In reply to Pooja Katiyar

Add support for UCSI SET_PDOS command as per UCSI specification v2.1 and above to debugfs.

---
 drivers/usb/typec/ucsi/debugfs.c | 6 ++++++
 drivers/usb/typec/ucsi/ucsi.h    | 4 ++++
 2 files changed, 10 insertions(+)
drivers/usb/typec/ucsi/debugfs.c +6 -0
index 004587ce3427..1c8003121d6e 100644
@@ -36,6 +36,12 @@ static int ucsi_cmd(void *data, u64 val)
 	case UCSI_SET_NEW_CAM:
 		ret = ucsi_send_command(ucsi, val, NULL, 0);
 		break;
+	case UCSI_SET_PDOS:
+		ret = ucsi_send_message_out(ucsi, ucsi->debugfs->message_out,
+					    UCSI_COMMAND_DATA_LEN(val));
+		if (!ret)
+			ret = ucsi_send_command(ucsi, val, NULL, 0);
+		break;
 	case UCSI_GET_CAPABILITY:
 	case UCSI_GET_CONNECTOR_CAPABILITY:
 	case UCSI_GET_ALTERNATE_MODES:
drivers/usb/typec/ucsi/ucsi.h +4 -0
index e7453b055ff7..50341c40d80a 100644
@@ -130,6 +130,7 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
 #define UCSI_GET_CAM_CS			0x18
 #define UCSI_SET_SINK_PATH			0x1c
 #define UCSI_GET_LPM_PPM_INFO			0x22
+#define UCSI_SET_PDOS				0x1d
 
 #define UCSI_CONNECTOR_NUMBER(_num_)		((u64)(_num_) << 16)
 #define UCSI_COMMAND(_cmd_)			((_cmd_) & 0xff)
@@ -204,6 +205,9 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
 #define   UCSI_GET_PD_MESSAGE_TYPE_IDENTITY	4
 #define   UCSI_GET_PD_MESSAGE_TYPE_REVISION	5
 
+/* Data length bits */
+#define UCSI_COMMAND_DATA_LEN(_cmd_)		(((_cmd_) >> 8) & GENMASK(7, 0))
+
 /* -------------------------------------------------------------------------- */
 
 /* Error information returned by PPM in response to GET_ERROR_STATUS command. */
Signature · 1 line
2.34.1
#5 lore raw
Quoted 15 lines · Pooja Katiyar

Add support for UCSI SET_PDOS command as per UCSI specification v2.1 and above to debugfs.

---
 drivers/usb/typec/ucsi/debugfs.c | 6 ++++++
 drivers/usb/typec/ucsi/ucsi.h    | 4 ++++
 2 files changed, 10 insertions(+)
drivers/usb/typec/ucsi/debugfs.c +0 -0
index 004587ce3427..1c8003121d6e 100644

drivers/usb/typec/ucsi/debugfs.c static int ucsi_cmd(void *data, u64 val) · line 41

Quoted 6 lines
drivers/usb/typec/ucsi/debugfs.c +3 -0
@@ -36,6 +36,12 @@ static int ucsi_cmd(void *data, u64 val)
 	case UCSI_SET_NEW_CAM:
 		ret = ucsi_send_command(ucsi, val, NULL, 0);
 		break;
+	case UCSI_SET_PDOS:
+		ret = ucsi_send_message_out(ucsi, ucsi->debugfs->message_out,
+					    UCSI_COMMAND_DATA_LEN(val));

I think this goes against current UCSI command support code. I'd suggest you to:

- extend .sync_control to also include message_out fields
- return -EINVAL if the write_message_out() callback is not set
- make ucsi_send_command() accept message_out data.

Quoted 6 lines
drivers/usb/typec/ucsi/debugfs.c +3 -0
+		if (!ret)
+			ret = ucsi_send_command(ucsi, val, NULL, 0);
+		break;
 	case UCSI_GET_CAPABILITY:
 	case UCSI_GET_CONNECTOR_CAPABILITY:
 	case UCSI_GET_ALTERNATE_MODES:
Signature · 2 lines
With best wishes
Dmitry
maintainer
#6 lore raw
Quoted 26 lines · Dmitry Baryshkov
Quoted 15 lines · Pooja Katiyar

Add support for UCSI SET_PDOS command as per UCSI specification v2.1 and above to debugfs.

---
 drivers/usb/typec/ucsi/debugfs.c | 6 ++++++
 drivers/usb/typec/ucsi/ucsi.h    | 4 ++++
 2 files changed, 10 insertions(+)
drivers/usb/typec/ucsi/debugfs.c +0 -0
index 004587ce3427..1c8003121d6e 100644

drivers/usb/typec/ucsi/debugfs.c static int ucsi_cmd(void *data, u64 val) · line 41

Quoted 6 lines
drivers/usb/typec/ucsi/debugfs.c +3 -0
@@ -36,6 +36,12 @@ static int ucsi_cmd(void *data, u64 val)
 	case UCSI_SET_NEW_CAM:
 		ret = ucsi_send_command(ucsi, val, NULL, 0);
 		break;
+	case UCSI_SET_PDOS:
+		ret = ucsi_send_message_out(ucsi, ucsi->debugfs->message_out,
+					    UCSI_COMMAND_DATA_LEN(val));

I think this goes against current UCSI command support code. I'd suggest you to:

Quoted 3 lines

- extend .sync_control to also include message_out fields
- return -EINVAL if the write_message_out() callback is not set
- make ucsi_send_command() accept message_out data.

This makes sense to me.

thanks,

Signature · 1 line
heikki