Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: typec: tcpci: Prevent Sink disconnection before vPpsShutdown in SPR PPS

The Source can drop its output voltage to the minimum of the requested
PPS APDO voltage range when it is in Current Limit Mode. If this voltage
falls within the range of vPpsShutdown, the Source initiates a Hard
Reset and discharges Vbus. However, currently the Sink may disconnect
before the voltage reaches vPpsShutdown, leading to unexpected behavior.

Prevent premature disconnection by setting the Sink's disconnect
threshold to the minimum vPpsShutdown value. Additionally, consider the
voltage drop due to IR drop when calculating the appropriate threshold.
This ensures a robust and reliable interaction between the Source and
Sink during SPR PPS Current Limit Mode operation.

Fixes: 4288debeaa4e ("usb: typec: tcpci: Fix up sink disconnect thresholds for PD")
Cc: stable <stable@kernel.org>
Signed-off-by: Kyle Tso <kyletso@google.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
Link: https://lore.kernel.org/r/20250114142435.2093857-1-kyletso@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Kyle Tso and committed by
Greg Kroah-Hartman
4d27afbf 983e3758

+16 -8
+9 -4
drivers/usb/typec/tcpm/tcpci.c
··· 27 27 #define VPPS_NEW_MIN_PERCENT 95 28 28 #define VPPS_VALID_MIN_MV 100 29 29 #define VSINKDISCONNECT_PD_MIN_PERCENT 90 30 + #define VPPS_SHUTDOWN_MIN_PERCENT 85 30 31 31 32 struct tcpci { 32 33 struct device *dev; ··· 367 366 } 368 367 369 368 static int tcpci_set_auto_vbus_discharge_threshold(struct tcpc_dev *dev, enum typec_pwr_opmode mode, 370 - bool pps_active, u32 requested_vbus_voltage_mv) 369 + bool pps_active, u32 requested_vbus_voltage_mv, 370 + u32 apdo_min_voltage_mv) 371 371 { 372 372 struct tcpci *tcpci = tcpc_to_tcpci(dev); 373 373 unsigned int pwr_ctrl, threshold = 0; ··· 390 388 threshold = AUTO_DISCHARGE_DEFAULT_THRESHOLD_MV; 391 389 } else if (mode == TYPEC_PWR_MODE_PD) { 392 390 if (pps_active) 393 - threshold = ((VPPS_NEW_MIN_PERCENT * requested_vbus_voltage_mv / 100) - 394 - VSINKPD_MIN_IR_DROP_MV - VPPS_VALID_MIN_MV) * 395 - VSINKDISCONNECT_PD_MIN_PERCENT / 100; 391 + /* 392 + * To prevent disconnect when the source is in Current Limit Mode. 393 + * Set the threshold to the lowest possible voltage vPpsShutdown (min) 394 + */ 395 + threshold = VPPS_SHUTDOWN_MIN_PERCENT * apdo_min_voltage_mv / 100 - 396 + VSINKPD_MIN_IR_DROP_MV; 396 397 else 397 398 threshold = ((VSRC_NEW_MIN_PERCENT * requested_vbus_voltage_mv / 100) - 398 399 VSINKPD_MIN_IR_DROP_MV - VSRC_VALID_MIN_MV) *
+5 -3
drivers/usb/typec/tcpm/tcpm.c
··· 2974 2974 return 0; 2975 2975 2976 2976 ret = port->tcpc->set_auto_vbus_discharge_threshold(port->tcpc, mode, pps_active, 2977 - requested_vbus_voltage); 2977 + requested_vbus_voltage, 2978 + port->pps_data.min_volt); 2978 2979 tcpm_log_force(port, 2979 - "set_auto_vbus_discharge_threshold mode:%d pps_active:%c vbus:%u ret:%d", 2980 - mode, pps_active ? 'y' : 'n', requested_vbus_voltage, ret); 2980 + "set_auto_vbus_discharge_threshold mode:%d pps_active:%c vbus:%u pps_apdo_min_volt:%u ret:%d", 2981 + mode, pps_active ? 'y' : 'n', requested_vbus_voltage, 2982 + port->pps_data.min_volt, ret); 2981 2983 2982 2984 return ret; 2983 2985 }
+2 -1
include/linux/usb/tcpm.h
··· 163 163 void (*frs_sourcing_vbus)(struct tcpc_dev *dev); 164 164 int (*enable_auto_vbus_discharge)(struct tcpc_dev *dev, bool enable); 165 165 int (*set_auto_vbus_discharge_threshold)(struct tcpc_dev *dev, enum typec_pwr_opmode mode, 166 - bool pps_active, u32 requested_vbus_voltage); 166 + bool pps_active, u32 requested_vbus_voltage, 167 + u32 pps_apdo_min_voltage); 167 168 bool (*is_vbus_vsafe0v)(struct tcpc_dev *dev); 168 169 void (*set_partner_usb_comm_capable)(struct tcpc_dev *dev, bool enable); 169 170 void (*check_contaminant)(struct tcpc_dev *dev);