Skip to content
/ linux Public

Commit b2bbcaa

Browse files
bleungatchromiumSasha Levin
authored andcommitted
usb: typec: ucsi: psy: Fix voltage and current max for non-Fixed PDOs
[ Upstream commit 6811e0a ] ucsi_psy_get_voltage_max and ucsi_psy_get_current_max are calculated using whichever pdo is in the last position of the src_pdos array, presuming it to be a fixed pdo, so the pdo_fixed_voltage or pdo_max_current helpers are used on that last pdo. However, non-Fixed PDOs such as Battery PDOs, Augmented PDOs (used for AVS and for PPS) may exist, and are always at the end of the array if they do. In the event one of these more advanced chargers are attached the helpers for fixed return mangled values. Here's an example case of a Google Pixel Flex Dual Port 67W USB-C Fast Charger with PPS support: POWER_SUPPLY_NAME=ucsi-source-psy-cros_ec_ucsi.4.auto2 POWER_SUPPLY_TYPE=USB POWER_SUPPLY_CHARGE_TYPE=Standard POWER_SUPPLY_USB_TYPE=C [PD] PD_PPS PD_DRP POWER_SUPPLY_ONLINE=1 POWER_SUPPLY_VOLTAGE_MIN=5000000 POWER_SUPPLY_VOLTAGE_MAX=13400000 POWER_SUPPLY_VOLTAGE_NOW=20000000 POWER_SUPPLY_CURRENT_MAX=5790000 POWER_SUPPLY_CURRENT_NOW=3250000 Voltage Max is reading as 13.4V, but that's an incorrect decode of the PPS APDO in the last position. Same goes for CURRENT_MAX. 5.79A is incorrect. Instead, enumerate through the src_pdos and filter just for Fixed PDOs for now, and find the one with the highest voltage and current respectively. After, from the same charger: POWER_SUPPLY_NAME=ucsi-source-psy-cros_ec_ucsi.4.auto2 POWER_SUPPLY_TYPE=USB POWER_SUPPLY_CHARGE_TYPE=Standard POWER_SUPPLY_USB_TYPE=C [PD] PD_PPS PD_DRP POWER_SUPPLY_ONLINE=1 POWER_SUPPLY_VOLTAGE_MIN=5000000 POWER_SUPPLY_VOLTAGE_MAX=20000000 POWER_SUPPLY_VOLTAGE_NOW=20000000 POWER_SUPPLY_CURRENT_MAX=4000000 POWER_SUPPLY_CURRENT_NOW=3250000 Signed-off-by: Benson Leung <bleung@chromium.org> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://patch.msgid.link/20251208174918.289394-3-bleung@chromium.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 32ccda4 commit b2bbcaa

File tree

1 file changed

+20
-10
lines changed
  • drivers/usb/typec/ucsi

1 file changed

+20
-10
lines changed

drivers/usb/typec/ucsi/psy.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,20 @@ static int ucsi_psy_get_voltage_max(struct ucsi_connector *con,
8787
union power_supply_propval *val)
8888
{
8989
u32 pdo;
90+
int max_voltage = 0;
9091

9192
switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
9293
case UCSI_CONSTAT_PWR_OPMODE_PD:
93-
if (con->num_pdos > 0) {
94-
pdo = con->src_pdos[con->num_pdos - 1];
95-
val->intval = pdo_fixed_voltage(pdo) * 1000;
96-
} else {
97-
val->intval = 0;
94+
for (int i = 0; i < con->num_pdos; i++) {
95+
int pdo_voltage = 0;
96+
97+
pdo = con->src_pdos[i];
98+
if (pdo_type(pdo) == PDO_TYPE_FIXED)
99+
pdo_voltage = pdo_fixed_voltage(pdo) * 1000;
100+
max_voltage = (pdo_voltage > max_voltage) ? pdo_voltage
101+
: max_voltage;
98102
}
103+
val->intval = max_voltage;
99104
break;
100105
case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0:
101106
case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5:
@@ -143,6 +148,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
143148
union power_supply_propval *val)
144149
{
145150
u32 pdo;
151+
int max_current = 0;
146152

147153
if (!(con->status.flags & UCSI_CONSTAT_CONNECTED)) {
148154
val->intval = 0;
@@ -151,12 +157,16 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
151157

152158
switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
153159
case UCSI_CONSTAT_PWR_OPMODE_PD:
154-
if (con->num_pdos > 0) {
155-
pdo = con->src_pdos[con->num_pdos - 1];
156-
val->intval = pdo_max_current(pdo) * 1000;
157-
} else {
158-
val->intval = 0;
160+
for (int i = 0; i < con->num_pdos; i++) {
161+
int pdo_current = 0;
162+
163+
pdo = con->src_pdos[i];
164+
if (pdo_type(pdo) == PDO_TYPE_FIXED)
165+
pdo_current = pdo_max_current(pdo) * 1000;
166+
max_current = (pdo_current > max_current) ? pdo_current
167+
: max_current;
159168
}
169+
val->intval = max_current;
160170
break;
161171
case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5:
162172
val->intval = UCSI_TYPEC_1_5_CURRENT * 1000;

0 commit comments

Comments
 (0)