* [PATCH] usb: typec: ucsi: Add support for READ_POWER_LEVEL command
@ 2025-06-30 0:15 Venkat Jayaraman
2025-06-30 5:04 ` Greg KH
0 siblings, 1 reply; 4+ messages in thread
From: Venkat Jayaraman @ 2025-06-30 0:15 UTC (permalink / raw)
To: linux-usb; +Cc: gregkh, venkat.jayaraman, pse.type-c.linux, Heikki Krogerus
Add support for UCSI READ_POWER_LEVEL command as per
UCSI specification v2.1 and above to debugfs.
Following power related fields will be exposed as files in debugfs:-
peak_current (Peak current),
avg_current (Average current) and
vbus_voltage (VBUS voltage)
These files will be updated either when a READ_POWER_LEVEL
command is sent from OS or when a device is connected.
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Venkat Jayaraman <venkat.jayaraman@intel.com>
---
drivers/usb/typec/ucsi/debugfs.c | 34 ++++++++++++++++++++++++++++++++
drivers/usb/typec/ucsi/ucsi.c | 16 +++++++++++++++
drivers/usb/typec/ucsi/ucsi.h | 13 ++++++++++++
3 files changed, 63 insertions(+)
diff --git a/drivers/usb/typec/ucsi/debugfs.c b/drivers/usb/typec/ucsi/debugfs.c
index 92ebf1a2defd..aa7a0f5c197a 100644
--- a/drivers/usb/typec/ucsi/debugfs.c
+++ b/drivers/usb/typec/ucsi/debugfs.c
@@ -35,6 +35,7 @@ static int ucsi_cmd(void *data, u64 val)
case UCSI_SET_SINK_PATH:
case UCSI_SET_NEW_CAM:
case UCSI_SET_USB:
+ case UCSI_READ_POWER_LEVEL:
ret = ucsi_send_command(ucsi, val, NULL, 0);
break;
case UCSI_GET_CAPABILITY:
@@ -80,6 +81,33 @@ static int ucsi_resp_show(struct seq_file *s, void *not_used)
}
DEFINE_SHOW_ATTRIBUTE(ucsi_resp);
+static int ucsi_peak_curr_show(struct seq_file *m, void *v)
+{
+ struct ucsi *ucsi = m->private;
+
+ seq_printf(m, "%u mA\n", ucsi->connector->peak_current);
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(ucsi_peak_curr);
+
+static int ucsi_avg_curr_show(struct seq_file *m, void *v)
+{
+ struct ucsi *ucsi = m->private;
+
+ seq_printf(m, "%u mA\n", ucsi->connector->avg_current);
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(ucsi_avg_curr);
+
+static int ucsi_vbus_volt_show(struct seq_file *m, void *v)
+{
+ struct ucsi *ucsi = m->private;
+
+ seq_printf(m, "%u mV\n", ucsi->connector->vbus_voltage);
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(ucsi_vbus_volt);
+
void ucsi_debugfs_register(struct ucsi *ucsi)
{
ucsi->debugfs = kzalloc(sizeof(*ucsi->debugfs), GFP_KERNEL);
@@ -89,6 +117,12 @@ 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("peak_current", 0400,
+ ucsi->debugfs->dentry, ucsi, &ucsi_peak_curr_fops);
+ debugfs_create_file("avg_current", 0400,
+ ucsi->debugfs->dentry, ucsi, &ucsi_avg_curr_fops);
+ debugfs_create_file("vbus_voltage", 0400,
+ ucsi->debugfs->dentry, ucsi, &ucsi_vbus_volt_fops);
}
void ucsi_debugfs_unregister(struct ucsi *ucsi)
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 01ce858a1a2b..8e0f0289a11a 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1218,9 +1218,11 @@ static void ucsi_handle_connector_change(struct work_struct *work)
struct ucsi_connector *con = container_of(work, struct ucsi_connector,
work);
struct ucsi *ucsi = con->ucsi;
+ u8 curr_scale, volt_scale;
enum typec_role role;
u16 change;
int ret;
+ u32 val;
mutex_lock(&con->lock);
@@ -1291,6 +1293,20 @@ static void ucsi_handle_connector_change(struct work_struct *work)
if (change & UCSI_CONSTAT_BC_CHANGE)
ucsi_port_psy_changed(con);
+ if (UCSI_CONSTAT(con, PWR_READING_READY_V2_1)) {
+ curr_scale = UCSI_CONSTAT(con, CURRENT_SCALE_V2_1);
+ volt_scale = UCSI_CONSTAT(con, VOLTAGE_SCALE_V2_1);
+
+ val = UCSI_CONSTAT(con, PEAK_CURRENT_V2_1);
+ con->peak_current = UCSI_CONSTAT_CURR_SCALE_MULT * curr_scale * val;
+
+ val = UCSI_CONSTAT(con, AVG_CURRENT_V2_1);
+ con->avg_current = UCSI_CONSTAT_CURR_SCALE_MULT * curr_scale * val;
+
+ val = UCSI_CONSTAT(con, VBUS_VOLTAGE_V2_1);
+ con->vbus_voltage = UCSI_CONSTAT_VOLT_SCALE_MULT * volt_scale * val;
+ }
+
out_unlock:
mutex_unlock(&con->lock);
}
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 5a8f947fcece..791f031ff276 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -129,6 +129,7 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
#define UCSI_GET_PD_MESSAGE 0x15
#define UCSI_GET_CAM_CS 0x18
#define UCSI_SET_SINK_PATH 0x1c
+#define UCSI_READ_POWER_LEVEL 0x1e
#define UCSI_SET_USB 0x21
#define UCSI_GET_LPM_PPM_INFO 0x22
@@ -357,6 +358,14 @@ struct ucsi_cable_property {
#define UCSI_CONSTAT_BC_SLOW_CHARGING 2
#define UCSI_CONSTAT_BC_TRICKLE_CHARGING 3
#define UCSI_CONSTAT_PD_VERSION_V1_2 UCSI_DECLARE_BITFIELD_V1_2(70, 16)
+#define UCSI_CONSTAT_PWR_READING_READY_V2_1 UCSI_DECLARE_BITFIELD_V2_1(89, 1)
+#define UCSI_CONSTAT_CURRENT_SCALE_V2_1 UCSI_DECLARE_BITFIELD_V2_1(90, 3)
+#define UCSI_CONSTAT_PEAK_CURRENT_V2_1 UCSI_DECLARE_BITFIELD_V2_1(93, 16)
+#define UCSI_CONSTAT_AVG_CURRENT_V2_1 UCSI_DECLARE_BITFIELD_V2_1(109, 16)
+#define UCSI_CONSTAT_VOLTAGE_SCALE_V2_1 UCSI_DECLARE_BITFIELD_V2_1(125, 4)
+#define UCSI_CONSTAT_VBUS_VOLTAGE_V2_1 UCSI_DECLARE_BITFIELD_V2_1(129, 16)
+#define UCSI_CONSTAT_CURR_SCALE_MULT 5
+#define UCSI_CONSTAT_VOLT_SCALE_MULT 5
/* Connector Status Change Bits. */
#define UCSI_CONSTAT_EXT_SUPPLY_CHANGE BIT(1)
@@ -516,6 +525,10 @@ struct ucsi_connector {
u32 src_pdos[PDO_MAX_OBJECTS];
int num_pdos;
+ u32 peak_current;
+ u32 avg_current;
+ u32 vbus_voltage;
+
/* USB PD objects */
struct usb_power_delivery *pd;
struct usb_power_delivery_capabilities *port_source_caps;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] usb: typec: ucsi: Add support for READ_POWER_LEVEL command
2025-06-30 0:15 [PATCH] usb: typec: ucsi: Add support for READ_POWER_LEVEL command Venkat Jayaraman
@ 2025-06-30 5:04 ` Greg KH
2025-06-30 5:04 ` Greg KH
2025-07-02 18:25 ` Jayaraman, Venkat
0 siblings, 2 replies; 4+ messages in thread
From: Greg KH @ 2025-06-30 5:04 UTC (permalink / raw)
To: Venkat Jayaraman; +Cc: linux-usb, pse.type-c.linux, Heikki Krogerus
On Sun, Jun 29, 2025 at 05:15:56PM -0700, Venkat Jayaraman wrote:
> @@ -89,6 +117,12 @@ 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("peak_current", 0400,
> + ucsi->debugfs->dentry, ucsi, &ucsi_peak_curr_fops);
> + debugfs_create_file("avg_current", 0400,
> + ucsi->debugfs->dentry, ucsi, &ucsi_avg_curr_fops);
> + debugfs_create_file("vbus_voltage", 0400,
> + ucsi->debugfs->dentry, ucsi, &ucsi_vbus_volt_fops);
You can have these all on one line, but not a big deal :)
And what are the units of these files?
> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> index 01ce858a1a2b..8e0f0289a11a 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -1218,9 +1218,11 @@ static void ucsi_handle_connector_change(struct work_struct *work)
> struct ucsi_connector *con = container_of(work, struct ucsi_connector,
> work);
> struct ucsi *ucsi = con->ucsi;
> + u8 curr_scale, volt_scale;
Odd extra ' '
> + if (UCSI_CONSTAT(con, PWR_READING_READY_V2_1)) {
> + curr_scale = UCSI_CONSTAT(con, CURRENT_SCALE_V2_1);
> + volt_scale = UCSI_CONSTAT(con, VOLTAGE_SCALE_V2_1);
> +
> + val = UCSI_CONSTAT(con, PEAK_CURRENT_V2_1);
> + con->peak_current = UCSI_CONSTAT_CURR_SCALE_MULT * curr_scale * val;
> +
> + val = UCSI_CONSTAT(con, AVG_CURRENT_V2_1);
> + con->avg_current = UCSI_CONSTAT_CURR_SCALE_MULT * curr_scale * val;
> +
> + val = UCSI_CONSTAT(con, VBUS_VOLTAGE_V2_1);
> + con->vbus_voltage = UCSI_CONSTAT_VOLT_SCALE_MULT * volt_scale * val;
These will never overflow, right?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] usb: typec: ucsi: Add support for READ_POWER_LEVEL command
2025-06-30 5:04 ` Greg KH
@ 2025-06-30 5:04 ` Greg KH
2025-07-02 18:25 ` Jayaraman, Venkat
1 sibling, 0 replies; 4+ messages in thread
From: Greg KH @ 2025-06-30 5:04 UTC (permalink / raw)
To: Venkat Jayaraman; +Cc: linux-usb, pse.type-c.linux, Heikki Krogerus
On Mon, Jun 30, 2025 at 07:04:14AM +0200, Greg KH wrote:
> And what are the units of these files?
nevermind, that's in the file output itself, I missed that first look.
greg k-h
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] usb: typec: ucsi: Add support for READ_POWER_LEVEL command
2025-06-30 5:04 ` Greg KH
2025-06-30 5:04 ` Greg KH
@ 2025-07-02 18:25 ` Jayaraman, Venkat
1 sibling, 0 replies; 4+ messages in thread
From: Jayaraman, Venkat @ 2025-07-02 18:25 UTC (permalink / raw)
To: Greg KH, Venkat Jayaraman; +Cc: linux-usb, pse.type-c.linux, Heikki Krogerus
Hi Greg,
On Sun, Jun 29, 2025 10:04:14PM -0700 , Greg KH wrote:
> On Sun, Jun 29, 2025 at 05:15:56PM -0700, Venkat Jayaraman wrote:
>> @@ -89,6 +117,12 @@ 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("peak_current", 0400,
>> + ucsi->debugfs->dentry, ucsi, &ucsi_peak_curr_fops);
>> + debugfs_create_file("avg_current", 0400,
>> + ucsi->debugfs->dentry, ucsi, &ucsi_avg_curr_fops);
>> + debugfs_create_file("vbus_voltage", 0400,
>> + ucsi->debugfs->dentry, ucsi, &ucsi_vbus_volt_fops);
> You can have these all on one line, but not a big deal :)
I can change that in the next revision.
> And what are the units of these files?
>
>> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
>> index 01ce858a1a2b..8e0f0289a11a 100644
>> --- a/drivers/usb/typec/ucsi/ucsi.c
>> +++ b/drivers/usb/typec/ucsi/ucsi.c
>> @@ -1218,9 +1218,11 @@ static void ucsi_handle_connector_change(struct work_struct *work)
>> struct ucsi_connector *con = container_of(work, struct ucsi_connector,
>> work);
>> struct ucsi *ucsi = con->ucsi;
>> + u8 curr_scale, volt_scale;
> Odd extra ' '
Will fix this in the next version.
>> + if (UCSI_CONSTAT(con, PWR_READING_READY_V2_1)) {
>> + curr_scale = UCSI_CONSTAT(con, CURRENT_SCALE_V2_1);
>> + volt_scale = UCSI_CONSTAT(con, VOLTAGE_SCALE_V2_1);
>> +
>> + val = UCSI_CONSTAT(con, PEAK_CURRENT_V2_1);
>> + con->peak_current = UCSI_CONSTAT_CURR_SCALE_MULT * curr_scale * val;
>> +
>> + val = UCSI_CONSTAT(con, AVG_CURRENT_V2_1);
>> + con->avg_current = UCSI_CONSTAT_CURR_SCALE_MULT * curr_scale * val;
>> +
>> + val = UCSI_CONSTAT(con, VBUS_VOLTAGE_V2_1);
>> + con->vbus_voltage = UCSI_CONSTAT_VOLT_SCALE_MULT * volt_scale * val;
> These will never overflow, right?
The values (val) are 16-bit max and there should be no overflow concern with u32 fields declared.
>
> thanks,
>
> greg k-h
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-07-02 18:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-30 0:15 [PATCH] usb: typec: ucsi: Add support for READ_POWER_LEVEL command Venkat Jayaraman
2025-06-30 5:04 ` Greg KH
2025-06-30 5:04 ` Greg KH
2025-07-02 18:25 ` Jayaraman, Venkat
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox