From 84de39ffad3cebd9b3569c941ebf64a8a9bba1d8 Mon Sep 17 00:00:00 2001 From: Jun Li Date: Wed, 9 Jan 2019 15:22:23 +0530 Subject: [PATCH] MLK-17108-2 usb: typec: support dead battery charging If the vbus is aready on and remote cc state is Rp while typec init, we think it's a dead battery case, this needs the PD session already setup by bootloader, so kernel can negotiate a new power session by soft reset, this patch use the exsiting flag vbus_never_low as boot from dead battery flag, but update the condition of setting it: not only check vbus, also the cc status to make sure remote is a power source, if yes, bypass the vbus sink disable. If the vbus is from local, we will still disable vbus charge so original code intention is kept. Acked-by: Peter Chen Signed-off-by: Li Jun Signed-off-by: Vipul Kumar --- drivers/usb/typec/tcpm.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index c1cd6254f5af..56a545a3d361 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -2749,7 +2749,9 @@ static void tcpm_reset_port(struct tcpm_port *port) tcpm_bist_handle(port, false); port->tcpc->set_pd_rx(port->tcpc, false); - tcpm_init_vbus(port); /* also disables charging */ + /* Don't disable charging if boot from dead battery */ + if (!port->vbus_never_low) + tcpm_init_vbus(port); tcpm_init_vconn(port); tcpm_set_current_limit(port, 0, 0); tcpm_set_polarity(port, TYPEC_POLARITY_CC1); @@ -4391,21 +4393,26 @@ static void tcpm_init(struct tcpm_port *port) { enum typec_cc_status cc1, cc2; - tcpm_reset_port(port); - /* - * XXX - * Should possibly wait for VBUS to settle if it was enabled locally - * since tcpm_reset_port() will disable VBUS. + * Possibly the vbus was enabled locally which is wrong, we can + * firstly disable power sink then start tcpm state transition + * to fix it, this is different from dead battery case which can + * detect RP on cc , in case of dead battery boot, we don't disable + * vbus sink for charging. */ + if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2)) + return; + port->vbus_present = port->tcpc->get_vbus(port->tcpc); - if (port->vbus_present) + if ((cc1 >= TYPEC_CC_RP_DEF || cc2 >= TYPEC_CC_RP_DEF) && + port->vbus_present) port->vbus_never_low = true; + tcpm_reset_port(port); + tcpm_set_state(port, tcpm_default_state(port), 0); - if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0) - _tcpm_cc_change(port, cc1, cc2); + _tcpm_cc_change(port, cc1, cc2); /* * Some adapters need a clean slate at startup, and won't recover -- 2.17.1