From 2d9841f98db4301748378d4574f9ab5172905f36 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Tue, 13 Apr 2021 19:39:59 -0700 Subject: [PATCH] FROMGIT: usb: typec: tcpm: Allow slow charging loops to comply to pSnkStby When a PD charger advertising Rp-3.0 is connected to a sink port, the sink port current limit would 3A, during SNK_DISCOVERY, till power negotiation starts. Once the negotiation starts the power limit needs to drop down to pSnkStby(500mA @ 5V) and to negotiated current limit once the explicit contract is in place. Not all charging loops can ramp up to 3A and drop down to 500mA within tSnkStdby which is 15ms. The port partner might hard reset if tSnkStdby is not met. To solve this problem, this patch introduces slow-charger-loop which when set makes the port request PD_P_SNK_STDBY_MW upon entering SNK_DISCOVERY(instead of 3A or the 1.5A during SNK_DISCOVERY) and the actual currrent limit after RX of PD_CTRL_PSRDY for PD link or during SNK_READY for non-pd link. Reviewed-by: Heikki Krogerus Signed-off-by: Badhri Jagan Sridharan Link: https://lore.kernel.org/r/20210414024000.4175263-2-badhri@google.com Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 1373fefc6243cc96b3565f0ffffadfac4ccfb977 https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-next) Signed-off-by: Greg Kroah-Hartman Change-Id: I811b7f9ec732da0cab715837737ea09ea4a5bbbf --- drivers/usb/typec/tcpm/tcpm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 9cbee89eca84..e275c74b9337 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -463,6 +463,12 @@ struct tcpm_port { /* Auto vbus discharge status */ bool auto_vbus_discharge_enabled; + /* + * When set, port requests PD_P_SNK_STDBY_MW upon entering SNK_DISCOVERY and + * the actual currrent limit after RX of PD_CTRL_PSRDY for PD link, + * SNK_READY for non-pd link. + */ + bool slow_charger_loop; #ifdef CONFIG_DEBUG_FS struct dentry *dentry; struct mutex logbuffer_lock; /* log buffer access lock */ @@ -4129,6 +4135,8 @@ static void run_state_machine(struct tcpm_port *port) port->supply_voltage, port->pd_capable, ¤t_limit, &adjust); + if (port->slow_charger_loop || (current_limit > PD_P_SNK_STDBY_MW / 5)) + current_limit = PD_P_SNK_STDBY_MW / 5; tcpm_set_current_limit(port, current_limit, 5000); tcpm_set_charge(port, true); tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0); @@ -4257,6 +4265,8 @@ static void run_state_machine(struct tcpm_port *port) if (adjust) tcpm_set_current_limit(port, current_limit, 5000); + if (!port->pd_capable && port->slow_charger_loop) + tcpm_set_current_limit(port, tcpm_get_current_limit(port), 5000); tcpm_swap_complete(port, 0); tcpm_typec_connect(port); mod_enable_frs_delayed_work(port, 0); @@ -5879,6 +5889,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, port->typec_caps.type = ret; port->port_type = port->typec_caps.type; + port->slow_charger_loop = fwnode_property_read_bool(fwnode, "slow-charger-loop"); if (port->port_type == TYPEC_PORT_SNK) goto sink;