nct38xx: hard disable sinking when cc is set to open/open

zork's TCPC does not want to go into CC OPEN/OPEN when
it is powered solely by the power that it will be
cutting off. This should have caused the system to
brown out and reboot but the TCPC keeps enough of the
power connection to not allow a brown out but locks
up the rest of the system from continuing. By disabling
the SNKEN bit in CONTROL_OUT register, this condition
goes away and we will brown out on batteryless cold
reboot as expected.

BUG=b:162016100
BRANCH=none
TEST=ectool reboot_ec cold (without a battery attached)

Signed-off-by: Denis Brockus <dbrockus@google.com>
Change-Id: Idb9597c978a9ba18f79ff158db6463af156707b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2333120
Tested-by: Denis Brockus <dbrockus@chromium.org>
Commit-Queue: Edward Hill <ecgh@chromium.org>
Reviewed-by: Edward Hill <ecgh@chromium.org>
Auto-Submit: Denis Brockus <dbrockus@chromium.org>
This commit is contained in:
Denis Brockus 2020-08-03 09:21:21 -06:00 committed by Commit Bot
parent ff9651857b
commit b8723d58a8
2 changed files with 49 additions and 5 deletions

View File

@ -2292,8 +2292,14 @@ static void tc_attached_snk_exit(const int port)
if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
set_vconn(port, 0);
/* Attached.SNK exit - disable AutoDischargeDisconnect */
tcpm_enable_auto_discharge_disconnect(port, 0);
/*
* Attached.SNK exit - disable AutoDischargeDisconnect
* NOTE: This should not happen if we are suspending. It will
* happen in tc_cc_open_entry if that is the path we are
* taking.
*/
if (!TC_CHK_FLAG(port, TC_FLAGS_SUSPEND))
tcpm_enable_auto_discharge_disconnect(port, 0);
}
/* Clear flags after checking Vconn status */
@ -3261,9 +3267,15 @@ static void tc_cc_open_entry(const int port)
/*
* Ensure we disable discharging before setting CC lines to open.
* If we were sourcing above, then we already drained Vbus. If partner
* is sourcing Vbus they will drain Vbus if they are PD-capable.
* is sourcing Vbus they will drain Vbus if they are PD-capable. This
* should only be done if a battery is present as a batteryless
* device will brown out when AutoDischargeDisconnect is disabled and
* we do not want this to happen until the set_cc open/open to make
* sure the TCPC has managed its internal states for disconnecting
* the only source of power it has.
*/
tcpm_enable_auto_discharge_disconnect(port, 0);
if (battery_is_present())
tcpm_enable_auto_discharge_disconnect(port, 0);
/* We may brown out after applying CC open, so flush console first. */
CPRINTS("C%d: Applying CC Open!", port);

View File

@ -109,6 +109,38 @@ static int nct38xx_tcpm_init(int port)
return nct38xx_init(port);
}
int nct38xx_tcpm_set_cc(int port, int pull)
{
/*
* Setting the CC lines to open/open requires that the NCT CTRL_OUT
* register has sink disabled. Otherwise the following happens, as
* described by Nuvoton:
*
* 1. You set CC lines to Open/Open. This is physically happening on
* the CC line.
* 2. Since CC is now Open/Open, the internal TCPC HW state machine
* is no longer in Attached.Snk and therefore our TCPC HW
* automatically opens the sink switch (de-assert the VBSNK_EN pin)
* 3. Since sink switch is open, the TCPC VCC voltage starts to drop.
* 4. When TCPC VCC gets below ~2.7V the TCPC will reset and therefore
* it will present Rd/Rd on the CC lines. Also the VBSNK_EN pin
* after reset is Hi-Z, so the sink switch will get closed again.
*/
if (pull == TYPEC_CC_OPEN) {
int rv;
/* Disable SNKEN, it will be re-enabled in tcpm_init path */
rv = tcpc_update8(port,
NCT38XX_REG_CTRL_OUT_EN,
NCT38XX_REG_CTRL_OUT_EN_SNKEN,
MASK_CLR);
if (rv)
return rv;
}
return tcpci_tcpm_set_cc(port, pull);
}
static void nct38xx_tcpc_alert(int port)
{
int alert, rv;
@ -167,7 +199,7 @@ const struct tcpm_drv nct38xx_tcpm_drv = {
.check_vbus_level = &tcpci_tcpm_check_vbus_level,
#endif
.select_rp_value = &tcpci_tcpm_select_rp_value,
.set_cc = &tcpci_tcpm_set_cc,
.set_cc = &nct38xx_tcpm_set_cc,
.set_polarity = &tcpci_tcpm_set_polarity,
.set_vconn = &tcpci_tcpm_set_vconn,
.set_msg_header = &tcpci_tcpm_set_msg_header,