mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
usb: typec: ucsi: Add support for READ_POWER_LEVEL command
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> Link: https://lore.kernel.org/r/20250814163028.18058-1-venkat.jayaraman@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c0485e864a
commit
c851b71fd6
@@ -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,9 @@ 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)
|
||||
|
||||
@@ -1217,9 +1217,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);
|
||||
}
|
||||
|
||||
@@ -131,6 +131,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
|
||||
|
||||
@@ -359,6 +360,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)
|
||||
@@ -519,6 +528,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;
|
||||
|
||||
Reference in New Issue
Block a user